spacemonk
Defining function with same arity but different map values in one of param
Hi! I might be asking a silly one, sorry for that and thanks for your time!
my aim is to implement quite simple logic:
the get_or_create_movie could be called with first param with “type” = “movie”, in that case I do not care about any other params and the code stays the same
if the first param contains “type” => “tv-series”, then the logic start to differ according to values. I feel that the straightforward approach I took looks not really pretty ![]()
def get_or_create_movie(%{ "type" => "movie" } = movie) do
# same movie code
end
def get_or_create_movie(%{ "type" => "movie" } = movie, _like_time) do
# same movie code
end
def get_or_create_movie(%{ "type" => "movie" } = movie, _like_time, _review_text) do
# same movie code
end
def get_or_create_movie(%{ "type" => "tv-series" } = series) do
# only series code
end
def get_or_create_movie(%{ "type" => "tv-series" } = series, like_time) do
# like_time only series code
end
def get_or_create_movie(%{ "type" => "tv-series" } = series, like_time, review_text) do
# like_time and review text only series code
end
the dyalizer complains (warning) that the clauses /2 and /3 was previously defined.
the function could be called with “type” = “movie” in the first param and with second and/or third params present
Marked As Solved
al2o3cr
Each arity (the number after the /) is effectively a separate function. You can capture one with the defaults by using a smaller number:
defmodule Foo do
def bar(x, y \\ 1, z \\ 2) do
{x, y, z}
end
end
Enum.map([:a, :b, :c], &Foo.bar/1)
# => [{:a, 1, 2}, {:b, 1, 2}, {:c, 1, 2}]
Enum.scan([:a, :b, :c], &Foo.bar/2)
# => [:a, {:b, :a, 2}, {:c, {:b, :a, 2}, 2}]
(The result for Enum.scan isn’t terribly relevant, it was just the first function that came to mind that takes a callback that expects two arguments.)
In both cases, the arguments that aren’t passed to the lower-arity versions Foo.bar/1 and Foo.bar/2 are filled in with the defaults.
It’s common in Erlang code to see a long series of function heads with short heads filling in parameters and calling longer ones. This is the same as what Elixir’s compiler builds:
def bar(x, y \\ 1, z \\ 2), do: ...
# is equivalent to
def bar(x), do: bar(x, 1, 2)
def bar(x, y), do: bar(x, y, 2)
def bar(x, y, z), do: ...
which is why you can capture bar/1 and bar/2 distinctly from bar/3
Also Liked
LostKobrakai
Can you normalize to just /3 functions? E.g. by using a default value if like_time or review_text are not passed.







