Studying LFPE, trouble with wildcards

Recently I began studying with the book “Learn Functional Programming with Elixir” by Ulisses Almeida (version P1.0).

It’s been a great start so far, but I’m in the middle of Chapter 3 (Pattern Matching) and this is the first time I’ve stepped in something I’ve completely failed to understand:

user_input = IO.gets "Write your ability score:\n"
{ability_score, _} = Integer.parse(user_input)
ability_modifier = (ability_score - 10) / 2
IO.puts "Your ability modifier is #{ability_modifier}."

Line 2 is what escapes me – it was literally just made clear what a tuple is and how it works. I don’t know why there would need to be a two-element tuple with a wildcard to match with what looks to return a single value, although I’ve confirmed any valid result gets assigned to ability_score just fine.

I find the following passage talking about functions returning tuples vs. atoms unclear as well.

Is this just a weird quirk of Elixir (or just Integer.parse specifically) that I need to get used to?

Integer.parse doesn’t return a single value but a tuple in the form {integer, remainder_of_the_binary} (or :error). So if you used a single value, then you would have needed to extract the first element to get the number.

With pattern matching, you are matching the first element of the parse return (ability_score), the other part is not needed in this context so it was discarded, but still needed to be there as the result of Integer.parse would be superimposed on the RHS and matches assigned.

Doc for parse: Integer — Elixir v1.12.3

1 Like

Pattern matching can be new and exciting. Have you heard of tuple or object de-structuring from other languages? It is similar to that.

The _ wildcard means “I don’t care about this variable”. In this instance, it means you don’t care about the remainder. You can use _remainder to discard and name it, which helps with readability.

Integer.parse returns a tuple of the form {integer, remainder}.

You can set the result of that function to a single variable:

result = Integer.parse("2.5")
# result is {2, ".5"}
{int, remainder} = result
# int is 2
# remainder is ".5"

Or you can match on the shape of the return value:

{int, remainder} = Integer.parse("2.5")
# int is 2
# remainder is ".5"

Which allows you to pick and choose which parts you care about:

{int, _remainder} = Integer.parse("2.5")
# int is 2
# _remainder is discarded

The official docs give a nice intro, and there are some other resources: elixir school, thinking elixir.

4 Likes

Thanks a lot for the examples and especially the links to further resources and specs – will have to keep the latter close at hand when working with the core modules.