1

2つの変数AとBを渡して、それらが同等かどうかをテストできるようにするためにif..else if、ステートメント内でErlangに条件を作成しようとしています。receive..end.

シェルで入力してみました:

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)代わりに2つの変数がある場合、同様にどのようにスポーンしPid = spawn(ifelse,receiving,[]).ますか?使ってみPid = spawn(ifelse,receiving(1,2),[]).ましたが、エラーになりました。

4

2 に答える 2

4

@rvirdingがコメントしたように、Erlangは単一の割り当てです。問題は、値を変数Pidに既にバインドしているため、新しい値をバインドできないという事実に関連している可能性があります。

シェル(実際のコードでは推奨されません)でのみ、f(Variable)を使用して単一の変数のバインドを解除できます。

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"

もう1つは、実際にアトムを使用できるため、「True」と「False」に文字列値を使用する必要がある理由がわからないことです。さらに、if-elseまたはcaseの後、プロセスが終了するため、コードは1回しか機能しません。再帰関数を使用して、この問題に取り組むことができます。

これは、両方の変更を加えたモジュールです。

-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
于 2013-03-13T09:10:59.560 に答える
1

ファイルに関数receiveing/2を定義している場合、それは次のようなものがあることを意味します。

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

receiving() ->
    some_code.

receiving(A,B) ->
    other_code.

あなたはそれをで呼ぶことができます

Pid = spawn(ifelse、receiveing、[1,2])。

ちなみに、ifステートメントをerlangで書くことは通常ありません。その理由は、1つのケースがどの条件にも一致しない場合、コードがクラッシュするためです。

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.

私はこれをシェルでテストしました:

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.
于 2013-03-13T05:47:24.890 に答える