Current section

Files

Jump to
monadex lib curry.ex
Raw

lib/curry.ex

defmodule Curry do
@moduledoc """
Simple module for currying functions.
"""
@doc """
Curries a given function.
A function that would normally take three parameters, for example, will take
three individual parameters instead. The curry macro works with anonymous
functions and captured named functions.
## Examples
iex> fun3 = &(&1 + &2 + &3)
iex> fun3.(3, 4, 5)
12
iex> curried3 = curry(fun3)
iex> curried3.(3).(4).(5)
12
iex> defmodule Curry.Sample do
...> def uncurried(x, y, z) do
...> x + y + z
...> end
...> end
iex> Curry.Sample.uncurried(3, 4, 5)
12
iex> captured3 = curry &Curry.Sample.uncurried/3
iex> captured3.(3).(4).(5)
12
"""
defmacro curry(fun) do
quote do: Curry.Helper.curry(unquote(fun))
end
end
defmodule Curry.Helper do
@moduledoc false
@doc false
@spec curry((... -> term)) :: (term -> term)
def curry(fun) when is_function(fun, 0), do: fun
def curry(fun) when is_function(fun), do: curry(fun, arity(fun), [])
@doc false
defp curry(fun, 0, args), do: apply(fun, Enum.reverse(args))
defp curry(fun, n, args), do: &curry(fun, n - 1, [&1 | args])
@doc false
defp arity(f) when is_function(f), do: arity(f, 0)
defp arity(f, n) when is_function(f, n), do: n
defp arity(f, n), do: arity(f, n + 1)
end