I'm currently studying Elixir and I'm reading "Functional Web Development with Elixir, OTP and Phoenix", which imo is a great book. Working at the state machine chapter, I came up with the following code:
defmodule IslandsEngine.Rules do
alias __MODULE__
defstruct state: :initialized
def new(), do: %Rules{}
def check(%Rules{state: :initialized} = rules, :add_player), do:
{:ok, %Rules{rules | state: :players_set}}
def check(_state, _action), do: :error
end
The code above should work as a fully functional state machine. I'll paste above a few of iex commands:
iex(1)> alias IslandsEngine.Rules
IslandsEngine.Rules
iex(2)> rules = Rules.new()
%IslandsEngine.Rules{state: :initialized}
iex(3)> {:ok, rules} = Rules.check(rules, :add_player)
{:ok, %IslandsEngine.Rules{state: :players_set}}
iex(4)> rules.state
:players_set
So as you can see, the state struct has changed from :initialized
to :add_player
. Great.
My question is: is state:
struct really immutable? I mean, the method check/1
returns a copy of the struct with a state: :players_set
statement, which follows a correct functional pattern... but how does it "overwrite" the current status without modifying it directly?
Thanks a lot!