如何在erlang案例中的不同案例之间进行交流

时间:2018-09-03 10:43:44

标签: erlang

我正在尝试做这样的事情:

test(Tester) ->
  case Tester of
         start -> X = 4 
         ok -> X = X + 5,
               Y = X/5;
         terminate -> Y
  end.

但这不完全是。我知道可以通过tail或简单递归来实现。 通常X和Y是不受约束的。

在不使用erlang全局变量的情况下,是否可以在这些情况之间进行通信?

3 个答案:

答案 0 :(得分:5)

Erlang是一种功能语言,这意味着我们不会在代码的不同部分之间进行通信,也不会在没有目的的情况下将值存储在变量中,我们只是计算返回值(有时会产生一些副作用)。如果我们在不同的代码分支中进行通用计算,则可以将其放在通用函数中。

test(Tester) ->
  case Tester of
         start     -> 4;
         ok        -> computeY();
         terminate -> computeY()
  end.

computeY() ->
    X = 4 + 5,
    X/5.

答案 1 :(得分:4)

如果您需要在case语句的任何子句主体中访问变量,则必须在case语句之前分配它,或者有时您可以在{ {1}}子句模式:

test(Arg) ->
    Size = get_size(Arg), % I will use 'Size' in each clause body
    case Arg of
        #{foo := Foo} -> % if Arg is an Erlang map and has key 'foo'
            % I can use 'Foo' only here:
            io:format("It's a map with size ~p and has key foo with value ~p\n", [Size, Foo]);
        [Baz|_] -> % if Arg is an Erlang list with at least one element
            % I can use 'Baz' only here and for example i can NOT use 'Foo' here:
            io:format("It's a list with size ~p and its first element is ~p\n", [Size, Baz]);
        _ ->
            io:format("Unwanted argument ~p with ~p size\n", [Arg, Size])
    end.

get_size(X) when is_map(X)  -> map_size(X);
get_size(X) when is_list(X) -> length(X);
get_size(_)                 -> unknown.

我将上面的代码放在名为fun的Erlang Test中,以便在外壳中使用它而无需编译模块文件:

1> Test([5,4,3,2,1]).
It's a list with size 5 and its first element is 5
ok

2> Test(#{key => value, foo => ':)'}).
It's a map with size 2 and has key foo with value ':)'
ok

3> Test([]).                          
Unwanted argument [] with 0 size
ok

4> Test(#{key => value}).             
Unwanted argument #{key => value} with 1 size
ok

5> Test(13).              
Unwanted argument 13 with unknown size
ok

如果您对变量绑定感到好奇,建议阅读this article

答案 2 :(得分:0)

要在Erlang中执行此操作,您将启动(产生)一个将X保留在内存中的进程以及应该响应的进程的PID(进程ID),除非您希望每次都传递一个不同的PID时间以及开始/确定/终止。 Erlang中的进程具有自己的内存,状态或loopData。生成一个知道如何处理特定消息的进程后,您将其传递给消息并通过将消息发回来进行回复。

start_test() ->
  TestPID = spawn(?MODULE, test, [self()]),
  TestPID ! start,
  receive
    X -> io:format("X is: ~p~n",[X]
  end,
  TestPID ! ok,
  receive
    {X,Y} -> io:format("X is: ~p, Y is: ~p~n",[X, Y]
  end,
  TestPID ! terminate,
  receive
    Y -> io:format("Y is: ~p~n",[Y]
  end.

test(PID) -> 
  receive
   start -> PID ! 4,
     test(4, undefined, PID);
   terminate -> undefined
  end.

test(X, Y, PID) ->
  receive
    ok -> PID ! {X+5, (X+5)/5},
      test(X+5, (X+5)/5, PID);
    terminate -> PID ! Y
  end.

别忘了创建模块并导出start_test / 0和test / 1

如果运行start_test(),则应获得输出

X is: 4
X is: 9, Y is: 1.8
Y is: 1.8