Skip to content

Instantly share code, notes, and snippets.

@charithe
Created January 4, 2015 15:10
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save charithe/75df4fcc52bbb635b138 to your computer and use it in GitHub Desktop.
Save charithe/75df4fcc52bbb635b138 to your computer and use it in GitHub Desktop.
Elixir Currying With Macros
defmodule Curry do
defmacro defcurry({func_name, _func_ctx, args}, do: body) do
num_args = Enum.count(args)
if num_args - 1 >= 1 do
new_args = Enum.take(args, num_args - 1)
quote do
def unquote(func_name)(unquote_splicing(args)) do
unquote(body)
end
def unquote(func_name)(unquote_splicing(new_args)) do
fn x -> unquote(func_name)(unquote_splicing(new_args),x) end
end
defcurry unquote(func_name)(unquote_splicing(new_args)) do
fn x -> unquote(func_name)(unquote_splicing(new_args),x) end
end
end
else
quote do
def unquote(func_name)(unquote_splicing(args)) do
unquote(body)
end
end
end
end
defmacro __using__(_opts) do
quote do
import unquote(__MODULE__), only: [defcurry: 2]
end
end
end
defmodule CurryHarness do
use Curry
defcurry my_curried_func(a, b, c, d) do
a + b + c + d
end
defcurry my_uncurried_func(a), do: a
end
ExUnit.start
defmodule CurryTest do
use ExUnit.Case
test "original function" do
assert CurryHarness.my_curried_func(1,2,3,4) == 10
end
test "three args function" do
assert CurryHarness.my_curried_func(1,2,3).(4) == 10
end
test "two args function" do
assert CurryHarness.my_curried_func(1,2).(3).(4) == 10
end
test "one arg function" do
assert CurryHarness.my_curried_func(1).(2).(3).(4) == 10
end
test "uncurried function" do
assert CurryHarness.my_uncurried_func(30) == 30
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment