fireproofsocks

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

rvirding

Creator of Erlang

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. :wink:

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.

11
Post #7
rvirding

rvirding

Creator of Erlang

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). :wink:

kokolegorille

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.

Where Next?

Popular in Discussions Top

PragTob
Hello everyone, I know we had quite some threads (read through lots of them) about background job processing but it remains a hotly deba...
New
blackode
Elixir Upgrading is so Simple in Ubuntu and It worked for me Ubuntu 16.04 git clone https://github.com/elixir-lang/elixir.git cd elixir...
New
arpan
Hello everyone :wave: Today I am very excited to announce a project that I have been working on for almost 3 months now. The project is...
New
Fl4m3Ph03n1x
Background A few days ago I was listening to The future of Elixir from Elixir Talks, with Dave Thomas (@pragdave ) and Brian Mitchell. I...
New
New
nburkley
AWS re:Invent is on at the moment with some interesting announcements. One new feature in particular is the Lambda Runtime API for AWS La...
New
Qqwy
Looking at the stacks that existing large companies have used, WhatsApp internally uses Mnesia to store the messages, while Discord uses ...
New
rms.mrcs
A couple of days ago I was discussing with a friend about different approaches to write microservices. He said that if he was going to w...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 42842 311
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35953 110
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement