Передача сообщений Erlang между процессами

Я пишу код, который читает два входных файла и проверяет, присутствуют ли слова из первого файла во втором файле. Я хочу проверять элементы списка один за другим через передачу сообщений процесса.

Вот мой код:

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.

Проблема в том, что когда я хочу отправить элемент списка, он отправляет только первый элемент. Как я могу изменить свой код, чтобы отправить все строки и проверить их?


person koko    schedule 24.01.2016    source источник
comment
@Steve Vinoski: я намного лучше разобрался в этом вопросе, и вот мой код, надеюсь, вы видите мои ошибки ...   -  person koko    schedule 24.01.2016


Ответы (1)


Основная проблема заключается в том, что ваша функция check2/0 получает только один элемент, а затем завершает работу. Ему нужно зациклиться, чтобы получить все элементы, и ему также нужно что-то, чтобы сказать ему, когда остановиться. Давайте изменим функции одну за другой ниже, начиная с start/0:

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

Изменение здесь заключается в том, что нет необходимости создавать check2/1, его можно просто запустить непосредственно с помощью start/0.

Далее, вот наша пересмотренная функция check1/1:

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

Во-первых, мы добавили новую строку в шаблон разделения, а также опцию trim_all, чтобы избавиться от пустых элементов из разделения. Мы также добавили атом stop в список элементов, которые мы отправляем в Pid2. Давайте посмотрим на нашу пересмотренную функцию check2/0, чтобы понять, почему:

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

Обратите внимание, что мы разделили исходную check2/0 на две функции: check2/0 и check2/1. Это связано с тем, что функция check2/1 должна быть рекурсивной, чтобы она могла получать все отправленные ей элементы:

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.

Обратите внимание, что внутри receive мы сначала проверяем, получили ли мы атом stop, и если получаем, то выходим из функции. В противном случае мы получаем и проверяем Element, а после этого рекурсивно вызываем check2/1, чтобы он мог получить либо следующий Element, либо stop атом.

person Steve Vinoski    schedule 24.01.2016
comment
большое спасибо за вашу помощь, у меня есть другая проблема, я пытаюсь отфильтровать найденный элемент, например, если найденный элемент является членом этого списка, ["amazing","good","great","intresting","wonderful","valuable","super","excellent","admirable","awesome"] напечатайте 1, иначе, если элемент является членом этого списка, ["bad","garbage","terrible","horrible","boring","poor","weak","nok awful", "second-rate] напечатайте (-1).. .Я хотел сделать это в check2/1, смешав два (случай) статуса, но это не работает... - person koko; 25.01.2016
comment
Вам нужно прочитать и пройти два списка, один для хороших записей и один для плохих. Используйте lists:member2 для проверки одного списка, как вы это уже делали, но в случае не найдено сделайте еще один случай, чтобы проверить другой список, также с помощью lists:member/2. - person Steve Vinoski; 25.01.2016