Эликсир понимания GenServer - PullRequest
0 голосов
/ 06 июля 2018

Я новичок в Elixir, читал книгу и делал несколько примеров. Вот фрагмент кода, который заставляет меня задать вопрос здесь:

defmodule Sequence.Server do
    use GenServer
    def init(initial_number)do 
        {:ok,initial_number}
    end

    def handle_call(:next_number, _from, current_number)do
        {:reply, current_number,current_number+1}    
    end 
end

Как я знаю, функция init вызывается, когда сервер инициализируется, и мы определяем некоторый параметр - который будет исходным состоянием сервера. Меня смущает то, что current_number и initial_number связаны друг с другом, я имею в виду, что нигде в коде мы не говорим что-то подобное

current_number = initial_number

Потому что, когда я вызываю GenServer.call(some_process_id, :next_number), он начинается с 100, например, если параметр start_link равен 100. Как Elixir понимает, что он должен начинаться с 100, когда у нас нет какого-либо сопоставления между начальным состоянием и current_number параметры

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Цель init/1 - настроить внутреннее состояние GenServer. Единственный способ изменить внутреннее состояние этого GenServer - это call -ing, cast -ing или отправка обычных сообщений (затем обработка handle_info/2 callback).

Эти функции (соответственно handle_call/3 и handle_cast/2) будут вызываться с внутренним состоянием GenServer, переданным в качестве последнего аргумента аргумента функции.

Рассмотрим сценарий:

  1. Вы инициализируете GenServer с номером 100.
  2. Вы отправляете сообщение (a call, если быть более точным) этому GenServer - :next_number.
  3. Это вызывает вашу функцию обратного вызова handle_call(:next_number, _from, current_number), где current_number имеет начальное значение 100.
  4. В качестве возвращаемого значения из этой функции вы указали кортеж: {:reply, current_number,current_number+1}, который вы должны понимать следующим образом: reply (первый элемент кортежа) означает, что он ответит вызывающей стороне; вторым элементом кортежа будет значение, возвращаемое вызывающей стороне (в этом случае это будет число 100); и последним элементом кортежа будет новое состояние GenServer - current_number+1, поэтому 101.
  5. Когда вы отправите еще :next_number call на этот GenServer, он будет следовать предыдущим шагам, за исключением того, что внутреннее состояние теперь будет 101, а после возврата из функции новое состояние будет 102 и т.д ...
0 голосов
/ 06 июля 2018

Результат init равен {:ok, initial_state}, где значение состояния содержится в GenServer.

Подпись handle_call на самом деле handle_call(request, from, current_state), ион возвращает {:reply, result, new_state}.

Это означает, что когда вы делаете GenServer.call(pid, :next_number), это приводит к вызову handle_call(:next_number, _from, state), где состояние - переданное как current_number - начинается как initial_number ирезультат handle_call сохраняет новое состояние со значением current_number.

При следующем вызове GenServer.call(pid, :next_number) он вызывается с новым состоянием, вы возвращаете новое-новое состояние и т. д....

...