gen_server handle_info/2 说明
gen_server handle_info/2 clarification
在阅读 Erlang 和 OTP 的实际操作时,我 运行 发现了一些关于记录的奇怪语法,我无法理解这些语法。我希望有人可以在这里澄清 handle_info 超时的情况:
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}.
具体来说,我不太确定这里发生了什么:
#state{lsok = LSock} = State
这似乎是某种反向赋值?您是在有效地说第二个参数将是#state 记录,将 lsock 值分配给 LSock 变量并将整个记录分配给 State?我只是从接下来两行中变量的使用方式推断出来的,但这种语法看起来很奇怪。
[编辑]
我在 shell 中对模式匹配和赋值做了更多测试,但它没有像我预期的那样工作:
2> 1 = A.
* 1: variable 'A' is unbound
3> A = 1.
1
4> {1,2}.
{1,2}
5> {1,2} = B.
* 1: variable 'B' is unbound
然后我 运行 这个测试函数,看看它是否只是在匹配函数参数中:
test_assignment(A = {X,Y},{W,X} = B) ->
io:format("Variable A is ~p~n",[A]),
io:format("Variable B is ~p~n",[B]).
24> c(test).
test.erl:21: Warning: variable 'W' is unused
test.erl:21: Warning: variable 'Y' is unused
{ok,test}
25> test:test_assignment({1,2},{3,4}).
** exception error: no function clause matching test:test_assignment({1,2},{3,4}) (test.erl, line 21)
记住,Erlang 中的"assignment" 是模式匹配。在您问题中给出的上下文中,
#state{lsock = LSock} = State
断言 State
绑定到 #state{}
记录的值,同时它将 LSock
变量绑定到 lsock
State
的字段。
所有函数参数定义都是模式,和
#state{lsock = LSock} = State
是一个模式,它将State绑定到作为函数调用参数传递的整个术语,同时断言它是一个记录状态并绑定State#state.lsock 到 LSock。在您的 shell 示例中,
A = 1.
1 = A.
是匹配表达式,其形式为
<pattern> = <expression>
因此,您只能在“=”的左侧引入和绑定新变量。对于演示模式内等号匹配的示例,您可以 运行 在 erlang 中轻松 shell:
1> ({X,Y} = Z) = {1,2}.
{1,2}
2> X.
1
3> Y.
2
4> Z.
{1,2}
另一方面,你的例子
test:test_assignment({1,2},{3,4}).
引发错误,因为在您定义的函数子句中,X 在模式 {X, Y}, {Z, X} 中使用了两次,无法匹配参数,因为显然 1 不等于 4。您可以尝试一个 shell:
5> TestAssignment = fun (A = {X, Y}, {W, X} = B) ->
5> io:format("Variable A is ~p~n", [A]),
5> io:format("Variable B is ~p~n", [B]) end.
6> TestAssignment ({1,2}, {3,4}).
** exception error: no function clause matching erl_eval:'-inside-an-interpreted-fun-'({1,2},{3,4})
7> TestAssignment ({1,2}, {3,1}).
Variable A is {1,2}
Variable B is {3,1}
ok
注意匹配表达式 returns rhs 表达式匹配。您现在应该明白,为什么会这样:
10> 4 = C.
* 1: variable 'C' is unbound
11> C = 4.
4
% 4 = 4, so this matches and returns 4:
12> 4 = C.
4
% now C is bound, so this is a match 4 = 5, not <anything, that will be bound to C> = 5:
13> C = 5.
** exception error: no match of right hand side value 5
在阅读 Erlang 和 OTP 的实际操作时,我 运行 发现了一些关于记录的奇怪语法,我无法理解这些语法。我希望有人可以在这里澄清 handle_info 超时的情况:
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}.
具体来说,我不太确定这里发生了什么:
#state{lsok = LSock} = State
这似乎是某种反向赋值?您是在有效地说第二个参数将是#state 记录,将 lsock 值分配给 LSock 变量并将整个记录分配给 State?我只是从接下来两行中变量的使用方式推断出来的,但这种语法看起来很奇怪。
[编辑]
我在 shell 中对模式匹配和赋值做了更多测试,但它没有像我预期的那样工作:
2> 1 = A.
* 1: variable 'A' is unbound
3> A = 1.
1
4> {1,2}.
{1,2}
5> {1,2} = B.
* 1: variable 'B' is unbound
然后我 运行 这个测试函数,看看它是否只是在匹配函数参数中:
test_assignment(A = {X,Y},{W,X} = B) ->
io:format("Variable A is ~p~n",[A]),
io:format("Variable B is ~p~n",[B]).
24> c(test).
test.erl:21: Warning: variable 'W' is unused
test.erl:21: Warning: variable 'Y' is unused
{ok,test}
25> test:test_assignment({1,2},{3,4}).
** exception error: no function clause matching test:test_assignment({1,2},{3,4}) (test.erl, line 21)
记住,Erlang 中的"assignment" 是模式匹配。在您问题中给出的上下文中,
#state{lsock = LSock} = State
断言 State
绑定到 #state{}
记录的值,同时它将 LSock
变量绑定到 lsock
State
的字段。
所有函数参数定义都是模式,和
#state{lsock = LSock} = State
是一个模式,它将State绑定到作为函数调用参数传递的整个术语,同时断言它是一个记录状态并绑定State#state.lsock 到 LSock。在您的 shell 示例中,
A = 1.
1 = A.
是匹配表达式,其形式为
<pattern> = <expression>
因此,您只能在“=”的左侧引入和绑定新变量。对于演示模式内等号匹配的示例,您可以 运行 在 erlang 中轻松 shell:
1> ({X,Y} = Z) = {1,2}.
{1,2}
2> X.
1
3> Y.
2
4> Z.
{1,2}
另一方面,你的例子
test:test_assignment({1,2},{3,4}).
引发错误,因为在您定义的函数子句中,X 在模式 {X, Y}, {Z, X} 中使用了两次,无法匹配参数,因为显然 1 不等于 4。您可以尝试一个 shell:
5> TestAssignment = fun (A = {X, Y}, {W, X} = B) ->
5> io:format("Variable A is ~p~n", [A]),
5> io:format("Variable B is ~p~n", [B]) end.
6> TestAssignment ({1,2}, {3,4}).
** exception error: no function clause matching erl_eval:'-inside-an-interpreted-fun-'({1,2},{3,4})
7> TestAssignment ({1,2}, {3,1}).
Variable A is {1,2}
Variable B is {3,1}
ok
注意匹配表达式 returns rhs 表达式匹配。您现在应该明白,为什么会这样:
10> 4 = C.
* 1: variable 'C' is unbound
11> C = 4.
4
% 4 = 4, so this matches and returns 4:
12> 4 = C.
4
% now C is bound, so this is a match 4 = 5, not <anything, that will be bound to C> = 5:
13> C = 5.
** exception error: no match of right hand side value 5