While watching Jose Valim doing advent of code 2021, I noticed him called function like this
def test(a) do
IO.puts(a)
end
test(_a = 5)
What is the purpose of using _a = 5 instead of 5? Is there a name for this technique?
While watching Jose Valim doing advent of code 2021, I noticed him called function like this
def test(a) do
IO.puts(a)
end
test(_a = 5)
What is the purpose of using _a = 5 instead of 5? Is there a name for this technique?
useful to not get lost when you have mutiple arguments, eg
iex(1)> foo = fn a,b,c,d -> {a,b,c,d} end
#Function<41.65746770/4 in :erl_eval.expr/5>
iex(2)> foo.(_a=1, _b=2, _c=3, _d=4)
{1, 2, 3, 4}
Note that this is different to eg pythons named arguments, where the names really have a meaning.
in elixir its just to help read the code and has no meaning.
iex(3)> foo.(_banana1=1, _banana2=2, _banana3=3, _banana4=4)
{1, 2, 3, 4}
You could also do
iex(4)> foo.(a=1, b=2, c=3, d=4)
{1, 2, 3, 4}
But’ll get a warning, therefore the _
But you’ll (re)bind the variables which is most likely not what you want.
see https://elixir-lang.org/getting-started/pattern-matching.html
In some cases, you don’t care about a particular value in a pattern. It is a common practice to bind those values to the underscore,
_
. For example, if only the head of the list matters to us, we can assign the tail to underscore:
nice trick!
Nice one too. I didn’t know you could define variables in function calls.
Actually, I also did not know that.
I thought you’d get an unused variable
warning, but indeed:
defmodule Temp do
def foo(a, b, c, d), do: IO.inspect({a, b, c, d}, label: :in_foo)
def bar() do
foo(a=1, b=2, c=3, d=4)
IO.inspect({a, b, c, d}, label: :after_foo)
end
end
iex(11)> Temp.bar
in_foo: {1, 2, 3, 4}
after_foo: {1, 2, 3, 4}
{1, 2, 3, 4}
So the _
is used here to hint, that the variable should be ignored.
But still, you’ll get the same result when changing the variable names in the call:
def bar() do
foo(k=1, l=2, m=3, n=4)
IO.inspect({k, l, m, n}, label: :after_foo)
end
while in python for example:
>>> def foo(a, b):
... print(f"first {a} then {b}")
...
>>> foo(1,2)
first 1 then 2
>>> foo(a=1,b=2)
first 1 then 2
>>> foo(b=1,a=2)
first 2 then 1
>>> foo(c=1,d=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'c'