-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add multiple anon function arities in defpartial #12
Comments
@OvermindDL1 expanded on "tuple calls" (see #25), and he also mentioned that it is going away. Returning anonymous functions with different arity heads is also an error. iex(6)> fn
...(6)> (a) -> a
...(6)> (a,b) -> {a,b}
...(6)> end
** (CompileError) iex:6: cannot mix clauses with different arities in anonymous functions The main problem is that only fixed arity lambdas can be returned in a function call (and this applies to macros as well). |
A simple (but ugly) solution: defmodule A do
defmacro defpartialx({fun_name, ctx, args}, do: body) do
scanned_args = [[]] ++ args_scan(args)
quote do
unquote do: make_curried_clauses(scanned_args, {fun_name, ctx, body})
end
end
defp make_curried_clauses([args], {fun_name, ctx, body}) do
quote do
def unquote({fun_name, ctx, args}), do: unquote(body)
end
end
defp make_curried_clauses([args|rest], {fun_name, ctx, _} = fun_attrs) do
quote do
def unquote({fun_name, ctx, args}) do
&apply(__MODULE__, unquote(fun_name), unquote(args) ++ List.wrap(&1))
end
unquote do: make_curried_clauses(rest, fun_attrs)
end
end
defp args_scan(args), do: Enum.scan(args, [], &(&2 ++ [&1]))
end
defmodule B do
import A
defpartialx m(a,b,c), do: a-b-c
end
iex(28)> B.m.([1,2,3,4,5])
-13
iex(29)> B.m(1,2).([3,4,5])
-13
iex(31)> B.m(1,2).([3,4]).(5)
-13
iex(32)> B.m.([1,2]).([3,4]).(5)
-13
iex(33)> B.m(1).(2).([3,4]).(5)
-13
iex(34)> B.m(1).([2,3]).([4,5])
-13 Had to re-write Note to self:
defpartial m(a,b,c), do: a-b-c
|
V
def m(), do: fn(a) -> fn(b) -> fn(c) -> a-b-c end end end
def m(a), do: m().(a)
def m(a,b), do: m(a).(b)
def m(a,b,c), do: m(a,b).(c)
# if I understood that correctly and def new(), do: fn(a) -> apply(__MODULE__, :new, [a] ) end
def new(a), do: fn(b) -> apply(__MODULE__, :new, [a] ++ [b]) end
def new(a,b), do: fn(c) -> apply(__MODULE__, :new, [a, b] ++ [c]) end
def new(a, b, c), do: a - b - c |
I'm facing this issue too. |
@korsmakolnikov You can work around it by returning a 2-arg function from your function directly, bit of a hack but it works. |
I know. The purpose of this macro is to have the strait tool as you could have in a functional ML-like-thing, I think... |
Current behaviour for
defpartial
is to give multiple options for the first invocation, but then you have to apply single arguments after that. It should return anonymous functions with multiple heads after being invoked to give a more true partial application.The text was updated successfully, but these errors were encountered: