Writing and compiling custom behaviours in Erlang

て烟熏妆下的殇ゞ 提交于 2019-12-24 02:39:12

问题


I'm trying to write and compile a custom behaviour in Erlang.

I cannot find any clear documentation on how to compile this behaviour.

-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([]).

my command for comiling is :

erlc.exe .\src\bla.erl

resulting:

bla.erl:24: function init/1 undefined

Anyone an idea on writing and compiling behaviours in erlang, please? any links?


回答1:


Defining behaviour callbacks results in an obligation towards your implementation of callback module. In erlang, modules are just function containers, not classes nor interfaces. Behaviours are based on runtime module name resolution Mod:fun(). OTP gen_server (check it) keeps its callback module name after you pass it in: gen_server:start_link(CallbackModuleName, Args, Opts) and here is code for applying callback init/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);
        ...

It's applying init/1 of passed callback module kept in Mod parameter, gets its last value, do what you want and keep going (or not, depends on that last value).

Assume we have module bla_impl which looks like this:

-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) -> ... .

And now you need to say in bla which module you use by:

-module(bla).
-export([start_link/1]).

start_link(Mod) -> Mod:init([]).

or maybe better solution is to read it from configuration:

-module(bla).
-export([start_link/0]).

start_link() -> 
    Mod = application:get_env(bla_app,  callback_module),
    Mod:init([]),
    ...

There is many ways for doing so.

As you see there is no magic here. This would work even without -behaviour(bla) nor specified callback with -callback. This is just an information for compiler, tools and documentation.

From erlang documentation: Behaviours

And btw. start_link function should spawn another process and link to it.

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


来源:https://stackoverflow.com/questions/27920362/writing-and-compiling-custom-behaviours-in-erlang

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!