Skip to content

Instantly share code, notes, and snippets.

@meh
Created December 16, 2013 17:29
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save meh/7990856 to your computer and use it in GitHub Desktop.
Save meh/7990856 to your computer and use it in GitHub Desktop.
defmodule Fun do
def arity(fun) do
case :erlang.fun_info(fun, :arity) do
{ :arity, arity } ->
arity
end
end
def adapt!(fun, 0) do
fn -> fun.([]) end
end
# the max number of arguments for anonymous functions is 20
Enum.reduce 1 .. 20, [], fn i, args ->
args = [{ :"arg#{i}", [], nil } | args]
def adapt!(fun, unquote(i)) do
fn unquote_splicing(args) -> fun.(unquote(args)) end
end
args
end
defmacro adapt(arity, do: block) do
quote do
fn(var!(arguments)) -> unquote(block) end |> adapt!(unquote(arity))
end
end
def partial(fun, partial) do
adapt arity(fun) - length(partial) do
fun |> apply(partial ++ arguments)
end
end
def complement(fun) do
adapt arity(fun) do
not apply(fun, arguments)
end
end
def lift(modifier) do
fn base ->
adapt arity(base) do
base |> apply(arguments) |> modifier.()
end
end
end
def comp(funs) do
funs |> Enum.reverse |> Enum.reduce arity(funs |> Enum.first), fn
outer, inner ->
adapt arity(inner) do
inner |> apply(arguments) |> outer.()
end
end
end
def juxt(funs) do
fn arg ->
funs |> Enum.map(&(&1.(arg)))
end
end
def separate(list, pred) do
juxt([&Enum.filter(&1, pred), &Enum.reject(&1, pred)]).(list)
end
def always(value, arity) do
adapt arity do
value
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment