Functional programming 仅使用不可变变量在函数式编程(Erlang)中存储用户输入信息
作为一名Erlang的初学者,我正在学习Erlang编程书(第二版)。我很难掌握如何专门使用函数式编程原理存储和定期更新外部信息(如间歇性用户输入) 以我现在的例子来说,我现在在并发编程部分(第12章)的开头,书中谈到了区域服务器。下面是我的变体 作为练习,我尝试在这个模块中添加一种方法来存储用户发出的所有请求。但是,尽管有一点递归编程的经验,在命令式语言的意义上,可变变量的缺乏在这个特殊的例子中似乎是致命的 我尝试在SE站点上查找一些相关资源,如和 但它并没有以实际的方式回答我的问题。我知道,我试图实现的目标可以通过使用ETS(甚至是数据库)来实现,或者通过使用一个新进程的进程内存来实现,该进程接收并维护自身的历史记录 但我真正想理解的是(以及这个问题的要点)是否可以使用通用函数式编程原则而不必使用特定于Erlang的工具来实现。代码段中注释掉的行表示我天真地期望第一步是什么样子Functional programming 仅使用不可变变量在函数式编程(Erlang)中存储用户输入信息,functional-programming,erlang,Functional Programming,Erlang,作为一名Erlang的初学者,我正在学习Erlang编程书(第二版)。我很难掌握如何专门使用函数式编程原理存储和定期更新外部信息(如间歇性用户输入) 以我现在的例子来说,我现在在并发编程部分(第12章)的开头,书中谈到了区域服务器。下面是我的变体 作为练习,我尝试在这个模块中添加一种方法来存储用户发出的所有请求。但是,尽管有一点递归编程的经验,在命令式语言的意义上,可变变量的缺乏在这个特殊的例子中似乎是致命的 我尝试在SE站点上查找一些相关资源,如和 但它并没有以实际的方式回答我的问题。我知道,
-module(geometry_server4).
-export([start/0, client/2, loop/0]).
start() ->
spawn(geometry_server4, loop, []).
client(Pid_server, Geom_tuple) ->
Pid_server ! {self(), Geom_tuple},
%ok = storerequests(Geom_tuple),
receive
{area, Pid_server, Area} -> io:format("Client: Area of ~p is ~p~n", [Geom_tuple, Area]);
{error, Error} -> io:format("~p~n", [Error])
end.
%storerequests(Geom_tuple) -> addtolist(Geom_tuple, get_history()).
%
%addtolist(Item, History) ->
% [Item | History].
%get_history() -> ???
loop() ->
receive
{Client, {rectangle, S1, S2}} ->
Area = S1 * S2,
Client ! {area, self(), Area},
loop();
{Client, {square, S}} ->
Area = S * S,
Client ! {area, self(), Area},
loop();
{Client, _} ->
Client ! {error, "invalid parameters"},
loop()
end.
根据本书,此玩具服务器在终端中被调用为:
1> c(geometry_server4).
2> P = geometry_server4:start().
3> geometry_server4:client(P, {square, 3}).
但我真正想理解的是什么(以及这一点)
问题)是否可以使用通用功能
无需使用Erlang特定工具的编程原则
是的,它可以。您可以使用循环变量来存储所谓的状态
首先,有几个初步要点:
ServerPid
在外壳中:
1> c(my).
{ok,my}
2> my:test().
{area,<0.64.0>,6}
{area,<0.64.0>,16}
{history,<0.64.0>,[{square,4},{rectangle,2,3}]}
{error,<0.64.0>,"invalid parameters"}
{history,<0.64.0>,[{error,"hello"},history,{square,4},{rectangle,2,3}]}
done
3>
1>c(我的)。
{好的,我的}
2> my:test()。
{区域,6}
{区域,16}
{历史,[{正方形,4},{矩形,2,3}]}
{错误,,“无效参数”}
{history,[{error,“hello”},history,{square,4},{rectangle,2,3}]}
完成
3>
确切地说,循环函数将接受一个参数,该参数将在每个循环中携带。@Yogesch,“一个循环变量”-这与我上面使用的循环函数类似吗?--很抱歉,我为您准备了一个示例,但我被一个愚蠢的错误挂断了电话。@Yogesch,这是一个很好的继续方法--努力一点总是能教会您更多。在函数式语言中,虽然t说变量是不可变的,但递归函数中的参数变量本质上是可变的。@Yogesch,在过去的几个月里,我也一直在慢慢地编写Erlang,并且我一直在github上发布我对练习的答案。我目前被困在第18章/Websockets上,因为书中的代码不再起作用了。@Yogesch,还有,如果你有时间,你应该在上查看免费的在线erlang课程。他们由编写Erlang编程的Simon Thompson教授,他们非常优秀。你会学到很多。我建议你按顺序学习这两门课程(先是功能课程,然后是并发课程),但功能课程目前正在运行,并发课程将在几周后开始。他们改变了那里的工作方式,所以我认为你可以得到一个免费课程,你可以参加考试,但是第二个课程你必须付费参加考试。
1> c(my).
{ok,my}
2> my:test().
{area,<0.64.0>,6}
{area,<0.64.0>,16}
{history,<0.64.0>,[{square,4},{rectangle,2,3}]}
{error,<0.64.0>,"invalid parameters"}
{history,<0.64.0>,[{error,"hello"},history,{square,4},{rectangle,2,3}]}
done
3>