Search code examples
elixirgen-server

What's the point of the :ok init argument in Elixir's GenServer example?


In Elixir's intro to GenServer, the client API starts the server with an :ok argument

def start_link(opts \\ []) do
  GenServer.start_link(__MODULE__, :ok, opts)
end

And the server's init function requires its argument to be :ok

def init(:ok) do
  {:ok, HashDict.new}
end

What's the point of passing and verifying :ok? Would it be any different if we were to omit this and instead write something like

def start_link(opts \\ []) do
  GenServer.start_link(__MODULE__, nil, opts)
end

def init(_) do
  {:ok, HashDict.new}
end

?


Solution

  • Its important to remember here that the second argument passed to start_link will become the argument of the init function. Because this is a simple example they have used atom like :ok and can be replaced by nil. You need to pass the second argument be it nil.

    So answering your question, in this example :ok can be replaced by nil. I think they used :ok since there must be an argument and :ok looks like a good choice(just a preference)

    In other situations you have to make use of this information to fetch some important data or for pattern matching

    defmodule ServerDrop do
       use GenServer
    
    defmodule State do
        defstruct count: 0
    end
    
    def start_link do
        GenServer.start_link(__MODULE__,:ok,[{:name,__MODULE__}])
        #GenServer.start_link(__MODULE__,[],[{:name,__MODULE__}])
    end
    
    def init(:ok) do
        {:ok,%State{count: 10}}
    end
    
    def init([]) do
        {:ok,%State{}}
    end
    
    #Code left out for brevity
    

    In other situations you many need to get some data

    def init(stash_pid) do
        current_number = Stash.get_value stash_pid
        {:ok,{current_number,stash_pid}}
    end