I'm working through the examples in Programming Elixir by Dave Thomas (Pragmatic Bookshelf). I've been using the REPL at http://tryelixir.online/, and have also tried Wandbox with the same results on this particular issue.
defmodule Sequence.Server do
use GenServer
def handle_call( :next_number, _from, current_number ) do
{ :reply, current_number, current_number + 1 }
end
def handle_cast( { :increment_number, delta }, current_number ) do
{ :no_reply, current_number + delta }
end
end
{ :ok, pid } = GenServer.start_link( Sequence.Server, 100 )
GenServer.call( pid, :next_number ) # returns 100
GenServer.call( pid, :next_number ) # returns 101
GenServer.call( pid, :next_number ) # returns 102
GenServer.cast( pid, { :increment_number, 200 } ) # should set the number to 302
GenServer.call( pid, :next_number ) # returns undefined
If I comment out the GenServer cast, then the last call works as expected. Conversely, if I comment out all the GenServer calls, the cast returns :ok. Otherwise, the calls work until the cast, and the call after the cast returns undefined. Setting trace on the debug options when the server is started also confirms this (when only the calls or only the cast are uncommented, not when both are). It seems as though the server state is not carried through on the cast.
This:
...
{ :ok, pid } = GenServer.start_link( Sequence.Server, 100, [ debug: [ :trace ] ] )
#GenServer.call( pid, :next_number ) # returns 100
#GenServer.call( pid, :next_number ) # returns 101
#GenServer.call( pid, :next_number ) # returns 102
GenServer.cast( pid, { :increment_number, 200 } ) # should set the number to 302
#GenServer.call( pid, :next_number ) # returns undefined
Returns this:
*DBG* <0.1066.0> got cast {increment_number,200}
:ok
While this:
...
{ :ok, pid } = GenServer.start_link( Sequence.Server, 100, [ debug: [ :trace ] ] )
GenServer.call( pid, :next_number ) # returns 100
GenServer.call( pid, :next_number ) # returns 101
GenServer.call( pid, :next_number ) # returns 102
#GenServer.cast( pid, { :increment_number, 200 } ) # should set the number to 302
GenServer.call( pid, :next_number ) # returns undefined
Returns this:
*DBG* <0.1078.0> got call next_number from <0.1073.0>
*DBG* <0.1078.0> sent 100 to <0.1073.0>, new state 101
*DBG* <0.1078.0> got call next_number from <0.1073.0>
*DBG* <0.1078.0> sent 101 to <0.1073.0>, new state 102
*DBG* <0.1078.0> got call next_number from <0.1073.0>
*DBG* <0.1078.0> sent 102 to <0.1073.0>, new state 103
*DBG* <0.1078.0> got call next_number from <0.1073.0>
*DBG* <0.1078.0> sent 103 to <0.1073.0>, new state 104
103
What's going on here? Searching through online Elixir documentation confirms this is still the valid syntax/arity/etc for cast and handle_cast. Nothing in the book's online errata indicates an error. This behavior is repeatable in at least two online REPLs.