Could anyone explain this function signature

Reading/practicing through “Functional Web Development with Elixir, OTP and Phoenix”, I came across the following module definition;

defmodule IslandsEngine.Rules do
  alias __MODULE__

  defstruct state: :initialized,
            player1: :islands_not_set,
            player2: :islands_not_set

  def new(), do:
    %Rules{}

  def check(%Rules{state: :initialized} = rules, :add_player), do:
    {:ok, %Rules{rules | state: :players_set}}

  ...
end

What is the reason for the first agument’s right hand side declaration (’= rules’) is it simply a definition of the working variable within scope ?

def check(%Rules{state: :initialized} = rules, :add_player), do:
{:ok, %Rules{rules | state: :players_set}}

Running iex -S mix I see no practical difference passing in a different ‘variable’ name or direct struct, but perhaps I am missing something obvious;

Interactive Elixir (1.7.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> alias IslandsEngine.Rules
IslandsEngine.Rules
iex(2)> things = Rules.new()
%IslandsEngine.Rules{
  player1: :islands_not_set,
  player2: :islands_not_set,
  state: :initialized
}
iex(3)> Rules.check(things, :add_player)
{:ok,
 %IslandsEngine.Rules{
   player1: :islands_not_set,
   player2: :islands_not_set,
   state: :players_set
 }}
iex(4)> Rules.check(%IslandsEngine.Rules{state: :initialized}, :add_player)
{:ok,
 %IslandsEngine.Rules{
   player1: :islands_not_set,
   player2: :islands_not_set,
   state: :players_set
 }}

What is the reason for the first agument’s right hand side declaration (’= rules’) ?

rules is the same as in:

def check(rules, :add_player), do:

the difference is that

def check(%Rules{state: :initialized} = rules, :add_player), do:

adds the constraint of a pattern match.

4 Likes

Anything that matches the pattern %Rules{state: :initialized} will be bound to rules in the function body.

2 Likes

Thanks for replying!

I reasoned that meanwhile…, two related questions;

  • Is there strict order rules, e.g. can it also be rules = %Rules{…} instead ?
  • Why doesn’t it complain about the other two keys that are defined within the module’s struct definition?
1 Like

Pattern matches on maps aren’t exact. The map can contain information in addition to the data that is matched.

1 Like
  • Is there strict order rules, e.g. can it also be rules = %Rules{…} instead ?

IIRC that order will work as well.

Why doesn’t it complain about the other two keys that are defined within the module’s struct definition?

Complain about what? It’s a pattern - not a value. The pattern doesn’t care about the player1: and player2: keys and their values.

1 Like

Yep, both orders work. Great book you’re going through, BTW!

1 Like