fireproofsocks
How to think about pattern matching vs. type-checking
This is more of a general question, but I’m wondering how other people in the community think about the pattern matching in function signatures.
Pattern matching is fairly straight-forward when you match on simple values, e.g.
def something([]), do: "Emtpy!"
I start to get some metal friction when I look at type-hinting when there are functions like this:
def something(c = %Plug.Conn{}), do: "Something with the conn"
At first glance, I would think that c contains the empty struct, but of course, it will have the FULL value of whatever was passed to the function so long as the input was of the proper type. In other words, it’s not really a pattern-match at all, it’s a type hint.
Granted, my confusion here is probably the baggage of seeing that syntax used not for type-hinting, but for supplying a default value in many other languages (e.g. PHP, Ruby, Python).
The pattern matching/type-hinting gets a bit stranger for me when it gets nested inside tuples. Consider the following example:
my_tuple = MyContext.get_resource_as_tuple()
case my_tuple do
{:ok, resource = %{status_id: "valid"}} -> result
{:ok, %{status: status}} -> "Boo. Status #{status} is not valid."
{:error, msg} -> "Error: #{msg}"
end
Again, the resource = %{status_id: "valid"} looks more like an assignment, and I have to remind myself how it actually works. Go, for example, omits the equals sign and puts the type after the variable when it is used as part of a type-check. PHP, puts the variable type in front of the variable when it’s used as part of a type-check.
How do others think about this when they’re walking through code?
Most Liked
rvirding
I quite agree with the opinion that writing %Plug.Conn{} = c feels much better in a pattern match, it is how you would write the match in code. Though some prefer the other way as they see it as first matching then binding the variable. But they are wrong. 
Also I just want to point out that you can use the = alias in any patterns anywhere so you can write patterns like {a, b, c} = t and [%Plug.Conn{} = c | rest]. You can have your cake and eat it,
I do just want to stress that both ways result in the same code so there is no “better” choice wrt efficiency.
rvirding
Yes, the meaning of the = is different in patterns and in the inline use.
In the inline use the = actually has the syntax pattern = expression where the expression on the RHS is first evaluated and then the value of the expression is matched against the pattern. So it has a very strictly defined right-to-left semantics.
However, in a pattern it is an alias where both sides are pattern matched and both matches must succeed. All the variables in both patterns are bound if the matches succeed. It is commonly used for the case where you want to match and extract parts of a structure and have a reference to the whole. Like in you examples with maps and structs. It lets you have your cake and it.
Using the same operator perhaps wasn’t the smartest thing but it was inherited from Erlang so you can blame them (me). 
kokolegorille
I use the other way around…
{:ok, %{status_id: "valid"} = resource}
It reminds me of JS destructuring and got used to this form, and it does not look like an assignement.







