Search code examples
functional-programmingerlangelixirerlang-otpgen-server

Elixir understanding GenServer


I am new to Elixir and was reading through a book and doing some examples. Here is the piece of code that makes me ask question here:

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

As I know the init function is called when the server is being initialized and we are defining some parameter - which will be the initial state of the server. The thing that makes me confused is that how current_number and the initial_number are related to each other, I mean nowhere in the code we are saying something like that

current_number = initial_number

Because when I call GenServer.call(some_process_id, :next_number) it starts from 100 for example if the parameter to start_link was 100. How does Elixir understands that it must start from 100 when we dont have any mapping between the initial state and the current_number parameters


Solution

  • The purpose of an init/1 is to setup up internal state of a GenServer. The only way to amend this GenServer's internal state, is via call-ing, cast-ing, or sending regular messages (then, being handled by handle_info/2 callback).

    Those functions (respectively, handle_call/3 and handle_cast/2) will be invoked with the GenServer's internal state passed in as the last argument of a function's argument.

    Consider the scenario:

    1. You're initialising the GenServer with number 100.
    2. You send a message (a call to be more specific) to this GenServer - :next_number.
    3. This invokes your handle_call(:next_number, _from, current_number) callback function, where current_number has the initial value of 100.
    4. As a return value from this function, you specified the tuple: {:reply, current_number,current_number+1}, which you should understand like: reply (first element of a tuple) indicates it will reply to the caller; the second element of the tuple will be the value returned to caller (in this case, it will be number 100); and the last element of the tuple will be the new state of a GenServer - current_number+1, so 101.
    5. When you send another :next_number call to this GenServer, it will follow the previous steps, except, the internal state will now be 101, and after returning from the function, the new state will be 102, etc...