Как общаться между разными ситуациями в случае Эрланга - PullRequest
0 голосов
/ 03 сентября 2018

Я пытаюсь сделать что-то вроде этого:

test(Tester) ->
  case Tester of
         start -> X = 4 
         ok -> X = X + 5,
               Y = X/5;
         terminate -> Y
  end.

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

Есть ли способ связи между этими случаями без использования глобальных переменных erlang?

Ответы [ 3 ]

0 голосов
/ 04 сентября 2018

Erlang - это функциональный язык, это означает, что мы не общаемся между различными частями кода и не храним значения в переменных без цели, мы просто вычисляем, чтобы вернуть значение (и иногда создаем некоторый побочный эффект). Если у нас есть общие вычисления в разных ветвях кода, мы можем просто поместить их в общую функцию.

test(Tester) ->
  case Tester of
         start     -> 4;
         ok        -> computeY();
         terminate -> computeY()
  end.

computeY() ->
    X = 4 + 5,
    X/5.
0 голосов
/ 16 сентября 2018

Чтобы сделать это в Erlang, вы должны запустить (порождать) процесс, который будет содержать X в памяти, а также PID (идентификатор процесса) процесса, на который он должен отвечать, если вы не хотите каждый раз передавать ему другой PID время вместе с началом / хорошо / закончить. Процессы в Erlang имеют свою собственную память, состояние или loopData. После того, как вы породили процесс, который знает, как обрабатывать определенные сообщения, вы передаете ему сообщения, и он отвечает, отправляя сообщение обратно.

start_test() ->
  TestPID = spawn(?MODULE, test, [self()]),
  TestPID ! start,
  receive
    X -> io:format("X is: ~p~n",[X]
  end,
  TestPID ! ok,
  receive
    {X,Y} -> io:format("X is: ~p, Y is: ~p~n",[X, Y]
  end,
  TestPID ! terminate,
  receive
    Y -> io:format("Y is: ~p~n",[Y]
  end.

test(PID) -> 
  receive
   start -> PID ! 4,
     test(4, undefined, PID);
   terminate -> undefined
  end.

test(X, Y, PID) ->
  receive
    ok -> PID ! {X+5, (X+5)/5},
      test(X+5, (X+5)/5, PID);
    terminate -> PID ! Y
  end.

Не забудьте создать модуль и экспортировать start_test / 0 и test / 1

Если вы запустите start_test (), вы должны получить вывод

X is: 4
X is: 9, Y is: 1.8
Y is: 1.8
0 голосов
/ 03 сентября 2018

Если вам нужен доступ к переменной в любом теле предложения оператора case, вы должны назначить его перед оператором case или иногда , вы можете назначить его в шаблоне предложения case:

test(Arg) ->
    Size = get_size(Arg), % I will use 'Size' in each clause body
    case Arg of
        #{foo := Foo} -> % if Arg is an Erlang map and has key 'foo'
            % I can use 'Foo' only here:
            io:format("It's a map with size ~p and has key foo with value ~p\n", [Size, Foo]);
        [Baz|_] -> % if Arg is an Erlang list with at least one element
            % I can use 'Baz' only here and for example i can NOT use 'Foo' here:
            io:format("It's a list with size ~p and its first element is ~p\n", [Size, Baz]);
        _ ->
            io:format("Unwanted argument ~p with ~p size\n", [Arg, Size])
    end.

get_size(X) when is_map(X)  -> map_size(X);
get_size(X) when is_list(X) -> length(X);
get_size(_)                 -> unknown.

Я поместил приведенный выше код в Erlang fun с именем Test, чтобы использовать его в оболочке без необходимости компилировать файл модуля:

1> Test([5,4,3,2,1]).
It's a list with size 5 and its first element is 5
ok

2> Test(#{key => value, foo => ':)'}).
It's a map with size 2 and has key foo with value ':)'
ok

3> Test([]).                          
Unwanted argument [] with 0 size
ok

4> Test(#{key => value}).             
Unwanted argument #{key => value} with 1 size
ok

5> Test(13).              
Unwanted argument 13 with unknown size
ok

Если вас интересует привязка переменных в данном случае, я рекомендую прочитать эту статью

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...