实现函数currying的常用方法有哪些?
例如。在Haskell:
times a b = a * b
-- This can then be used uncurried:
times 2 3 -- Result is 6
-- But there is also auto-currying:
(times 2) 3 -- This works too
在Julia中,一些内置程序支持这一点:
<(8, 7) # Result is false
<(7)(8) # Same
7 |> <(8) # Same
然而,用户定义的函数不会自动具有以下功能:
times(a, b) = a * b
times(2, 3) # Result is 6
3 |> times(2) # MethodError: no method matching times(::Int64)
我可以手动定义一个单参数版本,如下所示:
times(a) = b -> a * b
但我的问题是,是否有通用运算符或函数可以实现这一点,并适用于用户定义和内置函数?
为什么不使用curry.jl
times(a, b) = a * b
times_curry = curry(times)
times_curry(5)(2) ---> gives 10
如果没有宏,在Julia中解决这一问题将非常棘手(不可能?(,因为多重调度意味着在看到所有参数之前,您不知道最终将调度到哪个函数。我认为实现currying最简单的方法就是使用这样的结构:
julia> struct Curry
func::Function
args::Tuple
Curry(func, args...) = new(func, args)
end
julia> (curry::Curry)(x, args...) = Curry(curry.func, curry.args..., x, args...)
julia> (curry::Curry)() = curry.func(curry.args...)
julia> Curry(<)
Curry(<, ())
julia> Curry(<)(2)()
(::Base.Fix2{typeof(<), Int64}) (generic function with 1 method)
julia> Curry(<)(2)(3)()
true
julia> Curry(<, 2)
Curry(<, (2,))
julia> Curry(<, 2, 3)()
true
基本上,用至少一个参数调用Curry
会用新的参数创建一个新的Curry
,用0个参数调用它会"执行"整个过程。