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.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








