Is it bad to use pattern matching only to check type?

I’m new to Elixir and I frequently see this type of code, for example in the the context code generated by Phoenix:

def do_something_with_foo(%Foo{} = foo) do
  ..
end

My question is, when we are not actually doing destructuring to get something inside foo (e.g. %Foo{bar: bar} = foo) or having multiple function clauses where we need to disginguish between a Foo and something else, is it really a good idea to use pattern matching just to assert that foo has the type Foo? I kinda feel that typing information should be left to typespecs, and pattern matching should only be used when we actually need it. It feels like writing functions like this in Python:

def do_something_with_foo(foo):
  assert isinstance(foo, Foo)

…which is not idiomatic.

1 Like

It is completely fine to do so. It makes the code more readable, because readers get more context about the arguments, and it also helps the compiler to optimize and emit warnings.

12 Likes

Thanks for replying!

it also helps the compiler to optimize and emit warnings

Can you give some examples of this?

I would also say it’s a good idea, because simply putting that information in a typespec does nothing to actually ensure that the value passed is what you say it is at runtime. Pattern matching like this however would throw an error at runtime if you tried to pass it a value that wasn’t a struct. So you don’t need to do things like check for nil before accessing a structs fields, you know that you can only have a struct in this argument. This is also basically the same thing as guards in elixir, to check for things like is_list/1 or is_binary/1 and ensure that you know what data you’re working on in the function body.

2 Likes

Yep, this is key. I have fallen in love with pattern matching partially because it makes catching and fixing logic errors so much quicker and easier.

1 Like

It also allows for IDEs to provide better code completions, e.g. Elixir-LS is able to complete struct fields after

foo.
1 Like