From Mason Protter in Slack:
struct FullyCurried end
macro curried(fdef)
f = fdef.args[1].args[1]
fargs = fdef.args[1].args[2:end]
arity = length(fargs)
body = fdef.args[2]
err_str = "Too many arguments. Function $f only takes $arity arguments"
quote
begin
function $f(args...)
if length(args) < $arity
x -> $f((args..., x)...)
elseif length(args) == $arity
$f(FullyCurried(), args...)
else
throw($err_str)
end
end
$f(::FullyCurried, $(fargs...)) = $body
end
end |> esc
end
@curried foo(x, y, z) = (x^2 + y^2)/(x^2 + y^2 +z^2)
julia> foo(1)(2)(3)
0.35714285714285715
julia> foo(1, 2, 3)
0.35714285714285715```