初学者的 Erlang/OTP 行为 [英] Erlang/OTP behaviors for beginner
问题描述
我从Erlang and OTP in action"一书中了解到,行为这个词指的是:
As I understood from the "Erlang and OTP in action" book, the word behavior refers to:
- 行为接口,它是一组函数;
- 行为实现,即特定于应用程序的代码(回调模块);
- 行为容器,它是一个进程.
问题:
Erlang/OTP 初学者应该了解哪些行为?是否可以概括地描述和理解 OTP 行为的概念?
在 Elang/OTP 的上下文中,回调函数"实际上意味着什么?
我们可以将行为实现中的回调视为 Java 中重写的方法吗?
Can we consider the callbacks in a behaviour implemenation as methods overriden in Java?
书上说,下面代码中库函数'gen_server:start_link/4'的关联回调函数是'Module:init/1'.
The book says that the associated callback function for the library function 'gen_server:start_link/4' in the following code is 'Module:init/1'.
这是否意味着在 init/1 中我们调用了 gen_server:start_link/4 库函数?或者这意味着什么?
Does that mean that with init/1 we call the gen_server:start_link/4 library function? Or does that mean anything else?
-module(tr_server).
-behaviour(gen_server).
-include_lib("eunit/include/eunit.hrl").
%% API
-export([
start_link/1,
start_link/0,
get_count/0,
stop/0
]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-define(SERVER, ?MODULE).
-define(DEFAULT_PORT, 1055).
-record(state, {port, lsock, request_count = 0}).
%%%===================================================================
%%% API
%%%===================================================================
%%--------------------------------------------------------------------
%% @doc Starts the server.
%%
%% @spec start_link(Port::integer()) -> {ok, Pid}
%% where
%% Pid = pid()
%% @end
%%--------------------------------------------------------------------
start_link(Port) ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []).
%% @spec start_link() -> {ok, Pid}
%% @doc Calls `start_link(Port)' using the default port.
s tart_link() ->
start_link(?DEFAULT_PORT).
%%--------------------------------------------------------------------
%% @doc Fetches the number of requests made to this server.
%% @spec get_count() -> {ok, Count}
%% where
%% Count = integer()
%% @end
%%--------------------------------------------------------------------
get_count() ->
gen_server:call(?SERVER, get_count).
%%--------------------------------------------------------------------
%% @doc Stops the server.
%% @spec stop() -> ok
%% @end
%%--------------------------------------------------------------------
stop() ->
gen_server:cast(?SERVER, stop).
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init([Port]) ->
{ok, LSock} = gen_tcp:listen(Port, [{active, true}]),
{ok, #state{port = Port, lsock = LSock}, 0}.
handle_call(get_count, _From, State) ->
{reply, {ok, State#state.request_count}, State}.
handle_cast(stop, State) ->
{stop, normal, State}.
handle_info({tcp, Socket, RawData}, State) ->
do_rpc(Socket, RawData),
RequestCount = State#state.request_count,
{noreply, State#state{request_count = RequestCount + 1}};
handle_info(timeout, #state{lsock = LSock} = State) ->
{ok, _Sock} = gen_tcp:accept(LSock),
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%%===================================================================
%%% Internal functions
%%%===================================================================
do_rpc(Socket, RawData) ->
try
{M, F, A} = split_out_mfa(RawData),
Result = apply(M, F, A),
gen_tcp:send(Socket, io_lib:fwrite("~p~n", [Result]))
catch
_Class:Err ->
gen_tcp:send(Socket, io_lib:fwrite("~p~n", [Err]))
end.
split_out_mfa(RawData) ->
MFA = re:replace(RawData, "
$", "", [{return, list}]),
{match, [M, F, A]} =
re:run(MFA,
"(.*):(.*)s*\((.*)s*\)s*.s*$",
[{capture, [1,2,3], list}, ungreedy]),
{list_to_atom(M), list_to_atom(F), args_to_terms(A)}.
args_to_terms(RawArgs) ->
{ok, Toks, _Line} = erl_scan:string("[" ++ RawArgs ++ "]. ", 1),
{ok, Args} = erl_parse:parse_term(Toks),
Args.
%% test
start_test() ->
{ok, _} = tr_server:start_link(1055).
推荐答案
问: Erlang/OTP 初学者应该了解哪些行为?是吗可以描述和理解 OTP 行为的概念简而言之?
Q: What an Erlang/OTP beginner should know about behaviours? Is it possible to describe and understand the notion of OTP behaviour in a nutshell?
行为通常用于代码中,以便编译器可以根据其行为生成更直观的错误消息,即 application/supervisor/gen_server/gen_event/gen_fsm.
A behaviour is usually used in code so that the compiler can generate more intuitive error messages depending upon its behaviour i.e application/supervisor/gen_server/gen_event/gen_fsm.
它使编译器能够给出特定于行为的错误消息,例如:gen_server
It enables the compiler give error messages specific to the behaviour for ex: gen_server
问:回调函数"在上下文中的实际含义是什么?Elang/OTP?
Q: What 'callback function' does actually mean in the context of Elang/OTP?
回调函数可以说是取自GUI编程(至少类似).每当发生事件时,例如.鼠标单击有一个单独的函数来处理鼠标单击.
Callback function can be said to be taken from GUI programming (at least similar). Whenever an event occurs for ex. a mouse click there is a separate function that handles mouse click.
因此,无论何时,例如.gen_server 的导出函数是从另一个模块调用的,该函数可以具有不同模式的回调函数(handle_call/handle_cast).
Thus whenever for eg. an exported function of a gen_server is called from another module, that function can have a callback function (handle_call/handle_cast) having different patterns.
问:我们可以将行为实现中的回调视为方法吗?在 Java 中被覆盖?
Q: Can we consider the callbacks in a behaviour implementation as methods overridden in Java?
是的...也许...没有:)
Yeah...maybe...no :)
Q: 书上说是库的关联回调函数以下代码中的函数 'gen_server:start_link/4' 是'模块:init/1'.
Q: The book says that the associated callback function for the library function 'gen_server:start_link/4' in the following code is 'Module:init/1'.
gen_server:start_link 自己调用了 init 函数,正如 w55 所回答的......(抱歉,这个名字太大了).
gen_server:start_link calls init function by itself as answered by w55.... (sorry quite a big name).
希望我已经回答了您的所有疑问:)
Hope I have answered all your queries :)
这篇关于初学者的 Erlang/OTP 行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!