Create a gist now

Instantly share code, notes, and snippets.

@meh /lol.exs
Created Dec 16, 2013

What would you like to do?
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