How to save state in Erlang process?

I am learning Erlang and trying to figure out how I can and should save state inside a process.

For example, I am trying to write a program that sets a list of numbers in a file, tells me if a number appears in this file. My approach is to use two processes

  • a cache that reads the contents of the file into the set, then waits for the numbers to be checked and then answers whether they are displayed in the set.

    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.
    
  • a client that sends numbers to the cache and awaits a response trueor false.

    check_number(Number) ->
        NumbersPid ! {self(), Number},
        receive
            {NumbersPid, Is_member} ->
                Is_member
        end.
    

This approach is obviously naive as the file is read for each request. However, I am completely new to Erlang, and I don’t understand what the preferred way to keep state between different requests would be.

? , , ?

Update

, user601836, is_member_loop . , Erlang, - , Erlang.

, , - , .

+5
2

, is_member_loop(Data_file) , .

, , gen_server. , records gen_server ( ).

:

1) (yourmodule.erl) gen_server 2) init gen_server :

init([]) ->
    Numbers = read_numbers(Data_file),
{ok, #state{numbers=Numbers}}.

3) , gen_server

check_number(Number) ->
    gen_server:call(?MODULE, {check_number, Number}).

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}.

5) yourmodule.erl check_number

-export([check_number/1]).

, 4:

a) ,

b) , , gen_server - , , {check_number, Number}

. erlang,

+7

, , Erlang, , ETS. ,

read_numbers_to_ets(DataFile) ->
    Table = ets:new(numbers, [ordered_set]),
    insert_numbers(Table, DataFile),
    Table.

insert_numbers(Table, DataFile) ->
    case read_next_number(DataFile) of
    eof -> ok;
    Num -> ets:insert(numbers, {Num})
    end.

is_member

is_member(TableId, Number) ->
    case ets:match(TableId, {Number}) of
    [] -> false; %% no match from ets
    [[]] -> true %% ets found the number you're looking for in that table
    end.

, Data_file, is_member_loop .

+1

All Articles