erlang案例中不同案例情境之间的沟通

erlang案例中不同案例情境之间的沟通,erlang,Erlang,我正在尝试这样做: test(Tester) -> case Tester of start -> X = 4 ok -> X = X + 5, Y = X/5; terminate -> Y end. 但不完全是这样。我知道它可以通过尾部或简单的递归来实现。 通常X和Y是未绑定的 有没有办法在不使用erlang全局变量的情况下在这些情况下进行通信?如果需要访问case语句的任

我正在尝试这样做:

test(Tester) ->
  case Tester of
         start -> X = 4 
         ok -> X = X + 5,
               Y = X/5;
         terminate -> Y
  end.
但不完全是这样。我知道它可以通过尾部或简单的递归来实现。 通常X和Y是未绑定的


有没有办法在不使用erlang全局变量的情况下在这些情况下进行通信?

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

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.
我将上述代码放在名为
Test
的Erlang
fun
中,以便在shell中使用它,而无需编译模块文件:

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

如果您对case中的变量绑定感到好奇,我建议您阅读如果您需要访问
case
语句的任何子句体中的变量,您必须在
case
语句之前分配它,或者有时可以在
case
子句模式中分配它:

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.
我将上述代码放在名为
Test
的Erlang
fun
中,以便在shell中使用它,而无需编译模块文件:

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

如果您对这种情况下的变量绑定感到好奇,我建议您阅读Erlang是一种函数式语言,它意味着我们不会在代码的不同部分之间通信,也不会毫无目的地将值存储在变量中,我们只是计算返回值(有时会产生一些副作用)。如果我们在不同的代码分支中有共同的计算,我们可以简单地把它放在共同的函数中

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

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

Erlang是一种函数式语言,它意味着我们不会在代码的不同部分之间通信,也不会毫无目的地将值存储在变量中,我们只是计算返回值(有时会产生一些副作用)。如果我们在不同的代码分支中有共同的计算,我们可以简单地把它放在共同的函数中

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

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

要在Erlang中实现这一点,您需要启动(生成)一个进程,该进程将在内存中保存X以及它应该回复的进程的PID(进程id),除非您希望每次在start/ok/terminate中传递一个不同的PID。Erlang中的进程有自己的内存、状态或循环数据。在生成一个知道如何处理特定消息的进程之后,您将消息传递给它,它将通过发回消息进行回复

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\u test/0和test/1

如果运行start_test(),您应该会得到

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

要在Erlang中实现这一点,您需要启动(生成)一个进程,该进程将在内存中保存X以及它应该回复的进程的PID(进程id),除非您希望每次在start/ok/terminate中传递一个不同的PID。Erlang中的进程有自己的内存、状态或循环数据。在生成一个知道如何处理特定消息的进程之后,您将消息传递给它,它将通过发回消息进行回复

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\u test/0和test/1

如果运行start_test(),您应该会得到

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

非常感谢您提供的所有解决方案。上面给出的解决方案让我明白,我真正想要的东西在erlang中是不可能实现的。这是对函数式语言的一个很好的描述!非常感谢您提供的所有解决方案。上面给出的解决方案让我明白,我真正想要的东西在erlang中是不可能实现的。这是对函数式语言的一个很好的描述!你想解决的问题是什么?您得到了两个答案,并得出结论:您无法使用erlang实现您想要实现的目标。这不太可能是事实,但由于代码片段只是无效的erlang,没有人能真正帮助您。用另一种语言的代码示例或伪代码和/或一组测试用例(test(start)返回4;test(ok)返回1.8;test(terminate)返回请允许我们帮助您。我现在编辑了这个问题,请仔细阅读我的帖子。我希望有一个函数,当我发送atom start时,它将X初始化为4,当我发送atom ok时,它将向上一个X添加5,最后当我发送atom terminate时,它将返回Y。您试图解决的问题是什么?您得到了两个答案,并得出结论:您无法使用erlang实现您想要实现的目标。这不太可能是事实,但由于代码片段只是无效的erlang,没有人能真正帮助您。用另一种语言的代码示例或伪代码和/或一组测试用例(test(start)返回4;test(ok)返回1.8;test(terminate)返回请允许我们帮助您。我现在编辑了这个问题,请仔细阅读我的帖子。我希望有一个函数,当我发送atom start时,它将X初始化为4,当我发送atom ok时,它将向上一个X添加5,最后当我发送atom terminate时,它将返回Y。