我正在尝试在if..else if
语句中在Erlang中创建receive..end.
条件,以便传递两个变量A和B,以便可以测试它们的等效性。
在shell中我尝试输入:
6> Pid = spawn(ifelse,receiving,[]).
** exception error: no match of right hand side value <0.54.0>
7>
我想要的是使用Pid ! {self(), 1,2}.
和Pid ! {self(), 2,2}.
来测试这两种情况,但是出了点问题。
-module(ifelse).
-export([receiving/0]).
receiving() ->
receive
{Pid,A,B}->
if
A =:= B ->
io:format(" B equals A ~n"),
Pid ! "True";
A =/= B ->
io:format(" B does not equal A ~n"),
Pid ! "False";
true -> {error, wrong_value}
end
end.
顺便说一句,如果我有receiving(A,B)
代替两个变量,我将如何与Pid = spawn(ifelse,receiving,[]).
类似地生成?我尝试使用Pid = spawn(ifelse,receiving(1,2),[]).
但是出错了。
答案 0 :(得分:4)
正如@rvirding评论的那样,Erlang是单一的分配。您的问题可能与您已将值绑定到变量Pid的事实有关,因此您无法将任何新值绑定到它。
只有在shell中(不推荐在实际代码中)才能使用f(变量)取消绑定单个变量:
1> A = 4.
4
2> f(A).
ok
3> A = 5.
5
或使用f()
取消绑定所有变量
请注意,这仅用于测试目的。
据我所知,您的代码是正确的,即使我建议您使用case
和模式匹配而不是if
语句。
所以我会按如下方式重写你的代码:
-module(ifelse).
-export([receiving/0]).
receiving() ->
receive
{Pid, A, B} ->
case A =:= B of
true ->
Pid ! "True";
false ->
Pid ! "False"
end
end.
您可以按如下方式测试:
1> Pid = spawn(ifelse,receiving,[]).
<0.34.0>
2> ShellPid = self().
<0.32.0>
3> Pid ! {ShellPid, 4, 5}.
{0.32.0, 4, 5}
4> flush().
Shell got "False"
另一件事是我不明白为什么你应该使用字符串值“True”和“False”,因为你实际上可以使用原子。此外,您的代码只能运行一次,因为在if-else或case之后,进程就会死掉。您可以使用递归函数来解决此问题。
这是一个包含两个修改的模块:
-module(ifelse).
-export([receiving/0]).
receiving() ->
receive
{Pid, A, B} ->
Pid ! A =:= B
end,
receiving().
以下是如何测试它(在一个新的shell中,所以你不必使用f()):
1> Pid = spawn(ifelse,receiving,[]).
<0.34.0>
2> ShellPid = self().
<0.32.0>
3> Pid ! {ShellPid, 4, 5}.
{0.32.0, 4, 5}
4> flush().
Shell got false
5> Pid ! {ShellPid, 4, 4}.
{0.32.0, 4, 4}
6> flush().
Shell got true
答案 1 :(得分:1)
如果您在文件中定义了一个接收/ 2的函数,则表示您有类似的内容:
-module(ifelse).
-export([receiving/0,receiving/2]).
receiving() ->
some_code.
receiving(A,B) ->
other_code.
你可以用
来打电话Pid = spawn(ifelse,receive,[1,2])。
顺便说一句,在erlang中编写if语句并不常见,原因是如果一个case与任何条件都不匹配,代码就会崩溃。
5> F=fun(X) -> if (X rem 2) == 0 -> X+1 end end.
#Fun<erl_eval.6.82930912>
6> F(4).
5
7> F(5).
** exception error: no true branch found when evaluating an if expression
8>
如果你想避免这种情况,你必须有一个默认的警卫(然后它看起来像一个案例)。
8> F1=fun(X) -> if (X rem 2) == 0 -> X+1;
8> true -> X end end.
#Fun<erl_eval.6.82930912>
9> F1(4).
5
10> F1(5).
11>
编写函数的常用方法更像是:
receiving() ->
receive
{Pid,_A,_A} when is_pid(Pid) ->
% use the pattern matching to verify that the 2 elements are equal
% and a guard test to check that the first element is a pid.
% Note that in this case it is a strict equals. I use _A because the code doesn't
% care of the value itself
io:format(" B equals A ~n"),
Pid ! "True";
{Pid,_,_} when is_pid(Pid) ->
% use pattern maching to verify the that message is a tupple of 3 elements
% and a guard test to check that the first element is a pid.
% For the 2 last elements I use _, so the data is not bound to any variable,
% only the structure is tested
io:format(" B does not equal A ~n"),
Pid ! "False";
_ -> {error, wrong_value}
end.
我在shell中测试了这个:
14> F = fun() ->
14> receive
14> {Pid,_A,_A} when is_pid(Pid) ->
14> io:format(" B equals A ~n"),
14> Pid ! "True";
14> {Pid,_,_} when is_pid(Pid) ->
14> io:format(" B does not equal A ~n"),
14> Pid ! "False";
14> _ -> {error, wrong_value}
14> end
14> end.
#Fun<erl_eval.20.82930912>
15> Pid = spawn(F).
<0.58.0>
16> Pid ! {self(),1,2}.
B does not equal A
{<0.51.0>,1,2}
17> % the returm value of "proc ! Mess" is Mess. It is what we get on the console on previous line
17> flush(). % use flush() to get the messages received by the shell
Shell got "False"
ok
18> Pid ! {self(),test,test}. % the process Pid is terminated now. when we send a message to it,
18> % it is simply "lost".
{<0.51.0>,test,test}
19> % it is necessary though to use a new variable Pid1 and spawn a new process
19> % (see rvirding message and user601836 answer)
19> Pid1 = spawn(F).
<0.63.0>
20> Pid1 ! {self(),test,test}.
B equals A
{<0.51.0>,test,test}
21> flush().
Shell got "True"
ok
22> Pid2 = spawn(F).
<0.68.0>
23> Pid2 ! {hello,test,test}.
{hello,test,test}
24> flush().
ok
25> % of course there is no message sent back, no io:format to print something on the console,
25> % the returned value of the function in the error case is "lost".
25> % if you want to have a permanent process you must have a recursive loop,
25> % calling receiving() were needed.