3
votes

Say I have a function, that's slightly verbose and is called with the same arguments each time, this function is also required a lot to do some setup before any other functions from that module can be called within its callback.

SomeMod.called_a_lot(‘xx’, fn(y) ->
  SomeMod.needs_called_a_lot_to_be_called_first(‘do_stuff’)
end)

I imagine that I can wrap it like so:

defp easier_to_call(func) do
  SomeMod.called_a_lot(‘xx’, fn(y) -> func(y) end
end

then use it like so:

easier_to_call(fn(y) ->
  SomeMod.needs_called_a_lot_to_be_called_first(‘do_stuff’)
end)

How does one actually do this in Elixir?

4
Your code looks fine; just change func(y) to func.(y) since it's an anonymous function.Dogbert

4 Answers

2
votes

Your syntax is just a bit off for calling anonymous functions. You will need to use

func.(y)

instead of

func(y)

since it is an anonymous function.

See the Elixir Crash Course for a brief example.

1
votes

Dogbert's comment is correct. But since you don't modify the arguments, you could just pass the function on without wrapping it in an anonymous function:

defp easier_to_call(func) do
  SomeMod.called_a_lot(‘xx’, func)
end
1
votes

I don't really understand what exactly you're asking, but I feel like the capture operator (&) is what you're looking for.

An example use would be:

easier_func = &SomeMod.called_a_lot(‘xx’, &1)

easier_func.(fn(_y) ->
  SomeMod.needs_called_a_lot_to_be_called_first(‘do_stuff’)
end)

With &1 being the first parameter in the anonymous function.

If you need a multiple arity anonymous function then you can do:

easy_reduce = &Enum.reduce(&1, 0, &2)

easy_reduce.([1,2,3,4], fn(x, acc) -> acc + x end) # => 10
1
votes

Just to show another approach: it might be achieved with macro, that calls the function to be called first and then calls the block:

defmodule Test do
  defmacro with_prepended(arg, do: block) do
    quote do
      IO.inspect(unquote(arg), label: "In function")
      prepended(unquote(arg))
      unquote(block)
    end
  end
end

defmodule Tester do
  require Test

  defp prepended(arg), do: IO.inspect(arg, label: "In prepended")

  def fun(arg) do
    Test.with_prepended(arg) do
      IO.puts "Actual code"
    end
  end
end

Tester.fun(42)

#⇒ In function: 42
#⇒ In prepended: 42
#⇒ Actual code