Erlang Message passing between process

有些话、适合烂在心里 提交于 2020-01-07 15:20:20

问题


I am writing code that reads two input files and checks if the words in the first file are present in the second file. I want to check elements of the list one by one via process message passing.

Here is my code:

start()->
    Pid2 = spawn(?MODULE,check2,[]),
    spawn(?MODULE,check1,[Pid2]).

check1(Pid2) ->
    {ok, Data} = file:read_file("input.txt"),
    B = binary:split(Data, [<<" ">>], [global]),
    K = [binary_to_list(Item) || Item <- B],
    [Pid2 ! Element || Element <- K].

check2() ->
    {ok,IoDevice} = file:open("check.txt", [read]),
    L = string:tokens(io:get_line(IoDevice,""), "! ."),
    receive
        Element ->
            case lists:member(Element,L)of
                true ->
                    io:format(Element);
                false ->
                    io:format("not_ok")
            end
    end.

The problem is that when I want to send an element of the list, it sends just the first element. How can I modify my code to send all strings and check them?


回答1:


The primary issue is that your check2/0 function only receives a single element and then exits. It needs to loop to receive all elements, and it also needs something to tell it when to stop. Let's change the functions one by one below, starting with start/0:

start()->
    Pid2 = spawn(?MODULE,check2,[]),
    check1(Pid2).

The change here is that there's no need to spawn check2/1 — it can just be run directly by start/0.

Next, here's our revised check1/1 function:

check1(Pid2) ->
    {ok, Data} = file:read_file("input.txt"),
    B = binary:split(Data, [<<" ">>,<<"\n">>], [global,trim_all]),
    K = [binary_to_list(Item) || Item <- B],
    [Pid2 ! Element || Element <- K++[stop]].

First, we added newline to the split pattern, and also the trim_all option to get rid of empty elements from the split. We also appended the atom stop to the list of elements we send to Pid2. Let's look at our revised check2/0 function to see why:

check2() ->
    {ok,IoDevice} = file:open("check.txt", [read]),
    L = string:tokens(io:get_line(IoDevice,""), "! .\n"),
    check2(L).

Note that we've split the original check2/0 into two functions: check2/0 and check2/1. This is because the check2/1 function has to be recursive so it can receive all the elements sent to it:

check2(L) ->
    receive
        stop ->
            ok;
        Element ->
            case lists:member(Element,L)of
                true ->
                    io:format("found: ~s\n", [Element]);
                false ->
                    io:format("not found: ~s\n", [Element])
            end,
            check2(L)
    end.

Notice that inside the receive we first check to see if we've received the atom stop, and if we do, we exit the function. Otherwise, we receive and check an Element, and after that call check2/1 recursively so it can receive either the next Element or the stop atom.



来源:https://stackoverflow.com/questions/34979403/erlang-message-passing-between-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!