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
defmacro adapt(arity, do: block) when arity |> is_integer do
args = (0 .. arity - 1)
|> Enum.map &{ :"arg#{&1}", [], nil }
quote do
fun = fn(var!(arguments)) -> unquote(block) end
fn(unquote_splicing(args)) ->
fun.(unquote(args))
end
end
end
defmacro adapt(arity, do: block) do
quote do
block = unquote(Macro.escape(block))
arity = unquote(arity)
args = (0 .. unquote(arity) - 1)
|> Enum.map &{ :"arg#{&1}", [], nil }
quote do
fun = fn(var!(arguments)) -> unquote(block) end
fn(unquote_splicing(args)) ->
fun.(unquote(args))
end
end |> Code.eval_quoted(binding, __ENV__)
|> elem(0)
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