2013-03-12 72 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.