How does pattern matching with structs work?

“Evaluates to” is the gotcha here, the arguments of a function are always a “match context” which has special properties - this:

def some_fun(whole_arg = %{single_value: v}) do

and this:

def some_fun(%{single_value: v} = whole_arg) do

both result in the same function that matches a map with a single_value key and binds whole_arg and v.

This is not the same = that you get when writing those statements alone:

# requires `v` to be defined beforehand, binds a new map `whole_arg`
# always succeeds
whole_arg = %{single_value: v}

# vs

# requires `whole_arg` to be defined beforehand as a map, binds `v` 
# fails with MatchError if `whole_arg` does not have a :single_value key
%{single_value: v} = whole_arg

I suspect this is why it’s a common convention to write pattern-matches on structs on the left-hand side:

def may_attend_after_party(%Attendee{} = attendee) do

as it’s clearly distinguishable from the “evaluation” =.