在Julia中获取函数的通用方法



实现函数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个参数调用它会"执行"整个过程。

最新更新