2013-03-12 57 views
1

我试图在语句中在Erlang中创建一个if..else if条件,以传递两个变量A和B,以便可以测试它们的等价性。If..else if语句在receive..end语句中?

在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),[]).,但是出现错误。

+2

您得到的错误意味着shell中的变量'Pid'已经绑定。你产生了一个新的过程,所以你得到了一个新的与PID不匹配的PID。请记住,shell变量也是不可变的。 – rvirding 2013-03-13 00:27:07

回答

4

由于@rvirding评论,Erlang是单assignement。你的问题可能与你已经为变量Pid绑定了一个值的事实有关,因此你不能绑定任何新值。

只有外壳(在实际代码不推荐)可以使用F(变量)您解除绑定单个变量:

1> A = 4. 
4 
2> f(A). 
ok 
3> A = 5. 
5 

,或者取消绑定使用f() 通知所有的变量,这只是用于测试目的。

据我所见,你的代码是正确的,即使我建议你使用case和模式匹配而不是if语句。

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" 

另一件事是,我不明白为什么你应该使用一个字符串值:

-module(ifelse). 
-export([receiving/0]). 

receiving() -> 
    receive 
     {Pid, A, B} -> 
      case A =:= B of 
       true -> 
        Pid ! "True"; 
       false -> 
        Pid ! "False" 
      end 
    end. 

可以按如下测试:

所以如下我将重写代码因为你实际上可以使用原子,因此“真”和“假”。此外,你的代码只能工作一次,因为在if-else或case之后,进程就会死掉。您可以通过使用递归函数来解决此问题。

这里既与修改的模块:

-module(ifelse). 
-export([receiving/0]). 

receiving() -> 
    receive 
     {Pid, A, B} -> 
      Pid ! A =:= B 
    end, 
receiving(). 

,这里是如何测试它(在一个新的外壳,所以你不必使用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

如果你定义一个函数接收/ 2文件,这意味着你有类似:

-module(ifelse). 
-export([receiving/0,receiving/2]). 

receiving() -> 
    some_code. 

receiving(A,B) -> 
    other_code. 

您可以用

PID =产卵调用它(ifelse,接收, [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.