spacemonk

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 :wink:

  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

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

LostKobrakai

Can you normalize to just /3 functions? E.g. by using a default value if like_time or review_text are not passed.

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
Exadra37
Sometimes I want to check if the input into a function is not a blank string. My first approach: defmodule Example do def do_stuff(s...
New

Other popular topics Top

joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

We're in Beta

About us Mission Statement