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
的Erlangfun
中,以便在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
的Erlangfun
中,以便在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。