如何在Erlang进程中保存状态?

Rod*_*gue 6 erlang

我正在学习Erlang,并试图弄清楚我如何能够,并且应该在进程中保存状态.

例如,我正在尝试编写一个程序,该程序给出文件中的数字列表,告诉我该文件中是否出现了数字.我的方法是使用两个过程

  • 缓存,它将文件的内容读入一个集合,然后等待数字检查,然后回复它们是否出现在集合中.

    is_member_loop(Data_file) ->
        Numbers = read_numbers(Data_file),
        receive
            {From, Number} ->
                From ! {self(), lists:member(Number, Numbers)},
                is_member_loop(Data_file)
        end.
    
    Run Code Online (Sandbox Code Playgroud)
  • 客户端将数字发送到缓存并等待truefalse响应.

    check_number(Number) ->
        NumbersPid ! {self(), Number},
        receive
            {NumbersPid, Is_member} ->
                Is_member
        end.
    
    Run Code Online (Sandbox Code Playgroud)

这种方法显然很幼稚,因为每个请求都会读取文件.但是,我对Erlang很新,我不清楚在不同请求之间保持状态的首选方法是什么.

我应该使用流程词典吗?对于那种过程状态,我是否有不同的机制?

更新

根据user601836的建议,最明显的解决方案是将数字集作为参数传递给is_member_loop而不是文件名.它似乎是Erlang中的一个常见习语,并且在精彩的在线书籍中学习了一些Erlang.

但是,我认为,问题仍然适用于我希望在我的过程中保留的更复杂的状态.

use*_*836 8

简单的解决方案,您可以将is_member_loop(Data_file)数字列表传递给您的函数,而不是文件名.

处理状态时的最佳解决方案是使用gen_server.要了解更多信息,您应该查看记录gen_server行为(可能也很有用).

在实践中:

1)从基于gen_server行为的模块(yourmodule.erl)开始2)在gen_server的init函数中读取文件并将其作为state字段传递:

init([]) ->
    Numbers = read_numbers(Data_file),
{ok, #state{numbers=Numbers}}.
Run Code Online (Sandbox Code Playgroud)

3)编写一个函数,用于触发对gen_server的调用

check_number(Number) ->
    gen_server:call(?MODULE, {check_number, Number}).
Run Code Online (Sandbox Code Playgroud)

4)编写代码以处理从您的函数触发的消息

handle_call({check_number, Number}, _From, #state{numbers=Numbers} = State) ->
    Reply = lists:member(Number, Numbers)},
{reply, Reply, State};

handle_call(_Request, _From, State) ->
    Reply = ok,
{reply, Reply, State}.
Run Code Online (Sandbox Code Playgroud)

5)从yourmodule.erl函数导出 check_number

-export([check_number/1]).
Run Code Online (Sandbox Code Playgroud)

关于第4点需要解释的两件事:

a)我们使用模式匹配提取记录状态内的值

b)如您所见,我离开了通用句柄调用,否则每当收到与{check_number,Number}不同的消息时,由于错误的模式匹配,您的gen_server将失败

注意:如果您不熟悉erlang,请不要使用进程字典