【问题标题】:Writing and compiling custom behaviours in Erlang在 Erlang 中编写和编译自定义行为
【发布时间】:2015-01-14 19:08:01
【问题描述】:

我正在尝试在 Erlang 中编写和编译自定义行为

我找不到任何关于如何编译此行为的明确文档。

-module(bla).

-export([start_link/0,behaviour_info/1]).

behaviour_info(callbacks)->
    [{init,1}];
behaviour_info(_Other)->
    undefined.

%% -callback init(Args :: term()) ->
%%     {ok, State :: term()} | {ok, State :: term(), timeout()} |
%%     {stop, Reason :: term()} | ignore.

start_link()->
    init([]).

我的编译命令是:

erlc.exe .\src\bla.erl

结果:

bla.erl:24: function init/1 undefined

谁有关于在 erlang 中编写和编译行为的想法,好吗?有链接吗?

【问题讨论】:

    标签: erlang


    【解决方案1】:

    定义行为回调会导致您对回调模块的实现有义务。在 erlang 中,模块只是函数容器,而不是类或接口。行为基于运行时模块名称解析Mod:fun()。 OTP gen_server(检查它)在您传入后保留其回调模块名称:gen_server:start_link(CallbackModuleName, Args, Opts),这是applying callbackinit/1的代码:

    init_it(Starter, Parent, Name0, Mod, Args, Options) ->
        Name = name(Name0),
        Debug = debug_options(Name, Options),
        case catch Mod:init(Args) of
            {ok, State} ->
                proc_lib:init_ack(Starter, {ok, self()}),
                loop(Parent, Name, State, Mod, infinity, Debug);
            {ok, State, Timeout} ->
                proc_lib:init_ack(Starter, {ok, self()}),
                loop(Parent, Name, State, Mod, Timeout, Debug);
            ...
    

    它正在应用 init/1 保存在 Mod 参数中的传递回调模块,获取它的最后一个值,做你想做的事情并继续(或不做,取决于最后一个值)。

    假设我们有模块bla_impl,看起来像这样:

    -module(bla_impl).
    -behaviour(bla).
    -export([init/1, start_link/0]).
    
    start_link() -> bla:start_link(?MODULE). %% macro ?MODULE is resolved to bla_impl
    init(Args) -> ... .
    

    现在你需要在 bla 中说明你使用哪个模块:

    -module(bla).
    -export([start_link/1]).
    
    start_link(Mod) -> Mod:init([]).
    

    或者更好的解决方案是从配置中读取它:

    -module(bla).
    -export([start_link/0]).
    
    start_link() -> 
        Mod = application:get_env(bla_app,  callback_module),
        Mod:init([]),
        ...
    

    有很多方法可以做到这一点。

    如您所见,这里没有魔法。即使没有-behaviour(bla) 也没有使用-callback 指定回调,这也可以工作。这只是编译器、工具和文档的信息。

    来自 erlang 文档:Behaviours

    顺便说一句。 start_link 函数应该产生另一个进程并链接到它。

    start_link(Mod) ->
        spawn_link(Mod, init, [[]]).
    

    【讨论】:

    • 知道了!真的没有魔法!感谢 Lukasz 的快速而清晰的回答。
    猜你喜欢
    • 2012-03-15
    • 2016-02-07
    • 1970-01-01
    • 1970-01-01
    • 2017-04-28
    • 2017-07-14
    • 1970-01-01
    • 2013-10-27
    • 2017-11-02
    相关资源
    最近更新 更多