Why does this reduce work with this kind of syntax?

Hi everyone,

Would someone have a moment or two to explain what kind of sorcery is happening here?
Why does this reduce work with this kind of syntax?

  def list_users(args) do
    |> Enum.reduce(User, fn
      {:order, order}, query ->
        query |> order_by({^order, :email})
      {:filter, filter}, query ->
        query |> filter_with(filter)
      {:client_filter, client_filter}, query ->
        query |> filter_with(client_filter)
    |> Repo.all

If I join these lines it looks like this:

… {:order, order}, query -> query |> order_by({^order, :email}) See this here! {:filter, filter}, query -> …

Is there another, more sane way of writing this?


1 Like

It’s an anonymous function with multiple bodies. Just like named functions can have multiple bodies:

def foo([head | rest]), do: ...
def foo([]), do: nil

So can anonymous functions have multiple bodies:

  [head | rest] ->
  [] ->

But of course it is! It all makes sense now, thanks!

You do not need to have them on separate lines, using a semicolon (;) you can join them on a single line. I’d not suggest to do so very often, its not very good for readability :wink:

iex(1)> f = fn [] -> :empty; [_|_] -> :non_empty end
#Function<6.99386804/1 in :erl_eval.expr/5>
iex(2)> f.([])
iex(3)> f.([1,2,3])
iex(4)> f.(1)
** (FunctionClauseError) no function clause matching in :erl_eval."-inside-an-interpreted-fun-"/1

    The following arguments were given to :erl_eval."-inside-an-interpreted-fun-"/1:

        # 1

1 Like

More profound knowledge! Didn’t know any of this before. Thank you sir, excellent stuff!