在Erlang中编写和编译自定义行为 [英] Writing and compiling custom behaviours in Erlang

查看:123
本文介绍了在Erlang中编写和编译自定义行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我找不到任何关于如何编译这个文件的清晰文档行为。

  -module(bla)。 

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

behaviour_info(回调) - >
[{init,1}];
behaviour_info(_Other) - >
未定义。

%% -callback init(Args :: term()) - >
%% {ok,State :: term()} | {ok,State :: term(),timeout()} |
%% {stop,Reason :: term()} |忽视。

start_link() - >
init([])。

我的comiling命令是:

  erlc.exe .\src\bla.erl 

结果:

  bla.erl:24:function init / 1 undefined 
任何有关Erlang编写和编译行为的想法?任何链接?

解决方案

定义行为回调会导致您实施回调模块的义务。在erlang中,模块只是函数容器,而不是类和接口。行为是基于运行时模块名称解析 Mod:fun()。 OTP gen_server (检查它)保持其回调传递它后的模块名称: gen_server:start_link(CallbackModuleName,Args,Opts),这里是代码应用回调 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);
...

它正在应用 init / 1 传递的回调模块保存在 Mod 参数中,获取其最后一个值,执行所需和继续(或不依赖于最后一个值)。



假设我们有模块 bla_impl ,如下所示:

   - 模(bla_impl)。 
-behaviour(bla)。
-export([init / 1,start_link / 0])。

start_link() - >喇嘛:START_LINK(MODULE?)。 %%宏?MODULE被解析为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文档:行为



和btw。 start_link 函数应该产生另一个进程并链接到它。

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


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?

解决方案

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

这篇关于在Erlang中编写和编译自定义行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆