簡體   English   中英

是否僅通過MFA函數(apply / 3,spawn / 3等)才能調用Erlang回調? (自定義行為指南)

[英]Are Erlang -callbacks to be invoked only through MFA functions (apply/3, spawn/3, …)? (Custom Behaviors HOWTO)

這是我對這個簡單代碼的懷疑

-module(simple_server).
-export( [sayHello/0] ).

-callback say(Num :: term()) -> term().

sayHello() ->
    io:fwrite( "Hello 1: ~p\n", [ say(1) ]) ,
    io:fwrite( "Hello 2: ~p\n", [ say(2) ]) .

無法編譯:

$ erlc simple_server.erl
simple_server.erl:7: function say/1 undefined
simple_server.erl:8: function say/1 undefined

如果真是這樣,那么這在其他地方都沒有明確說明: 官方文檔 “ learn erlang”這個答案

您需要提供回調模塊的名稱,可以通過applyspawn來完成,但是您也可以使用變量作為模塊名稱來進行簡單的調用,例如CallbackModule:say(1)

因此,您可以執行以下任一操作:

sayHello(CallbackModule) ->
    io:fwrite( "Hello 1: ~p\n", [ CallbackModule:say(1) ]) ,
    io:fwrite( "Hello 2: ~p\n", [ CallbackModule:say(2) ]) .

要么

sayHello(CallbackModule) ->
    io:fwrite( "Hello 1: ~p\n", [ apply(CallbackModule, say, [1]) ]) ,
    io:fwrite( "Hello 2: ~p\n", [ apply(CallbackModule, say, [2]) ]) .

這兩個版本是等效的。

讓我們創建一個實現simple_server行為的回調模塊:

-module(my_callback).
-behaviour(simple_server).
-export([say/1]).

say(N) ->
    {N, is, the, loneliest, number}.

現在我們可以使用模塊名稱作為參數來調用simple_server:sayHello

> simple_server:sayHello(my_callback).
Hello 1: {1,is,the,loneliest,number}
Hello 2: {2,is,the,loneliest,number}

HOWTO Erlang自定義行為(模板方法模式)。

-1。 編寫一個通用模塊。 在這里,定義了一種算法,但是剩下一些步驟(Erlang命名法中的回調函數)供將來使用。

%% generic.erl   
-module(generic).
-export( [sayHello/1] ).

-callback say(Num :: term()) -> term(). %% future definition

%% generic algorithm: needs the reference to the provider module                                 
sayHello(ProviderModule) ->
  io:fwrite( "Hello 1: ~p\n", [ ProviderModule:say(1) ]) ,
  io:fwrite( "Hello 2: ~p\n", [ ProviderModule:say(2) ]) .

-2。 編譯generic.erl

erlc generic.erl

-(3。)嘗試編寫提供程序(回調)模塊

%% callbacks1.erl (fails to implement say/1 callback)
-module( callbacks1 ).
-behaviour( generic ).

-(4。)編譯callbacks1.erl: 使用-pa。 說出generic.beam在哪里。 (因此,發出了關於say / 1的預期警告)。

erlc -pa . callbacks1.erl
callbacks1.erl:2: Warning: undefined callback function say/1 (behaviour 'generic')

(注意:如果未指定-pa,則會得到以下信息:“ callbacks1.erl:2:警告:行為通用未定義”)

-3。 編寫正確的提供程序(回調)模塊。

%% callbacks2.erl
-module( callbacks2 ).
-behaviour( generic ).

-export( [say/1] ).

say(1) -> "good morning";
say(2) -> "bon jour";
say(_) -> "hi".

-4。 編譯它

erlc -pa . callbacks2.erl

(現在可以)。

-5。 編寫main.erl以使用回調模塊收集通用模塊。

%% main.erl
-module( main ).
-export( [main/0] ).

main() ->
    %% call the generic algorithm telling it what callback module to use
    generic:sayHello( callbacks2 ) 
    . % ()

-6。 編譯並運行main

erlc main.erl
erl -noshell -s main main -s init stop

我們得到:

Hello 1: "good morning"
Hello 2: "bon jour"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM