Bea*_*rtz 2 ruby functional-programming currying
Ruby 1.9内置支持currying支持两种处理proc的方法,它采用任意数量的参数:
my_proc = proc {|*x| x.max }
Run Code Online (Sandbox Code Playgroud)
1)curry没有争论:my_proc.curry.你将逗号分隔的参数传递给curried的proc,就像你对普通的proc一样.如果参数的数量是任意的,则无法实现正确的currying(如果某些参数不是splat,则会很有用)
2)curry带参数:my_proc.curry(n)这样,currying就会被应用,好像proc会接受n参数.例如:
my_proc.curry(3).call(2).call(5).call(1) #=> 5
Run Code Online (Sandbox Code Playgroud)
那么,你将如何通过任意数量的参数实现currying?那意味着,如果n没有给出?
我想到的一种方法是通过代理收集参数call然后解析procvia method_missing(如果除了call使用之外的任何方法/ call没有参数使用,请proc使用收集的参数调用),但我仍然在寻找其他方法实现它.
更新
正如Andy H所说,问题是什么时候停止晃动.对于我的目的,如果currying停止/ proc评估何时call调用任何方法或者call在没有参数的情况下调用,那就没关系.
内置curry方法不适合您.原因是它产生一个proc,只要它有足够的参数就可以进行评估.引用您链接到的文档:
一个咖喱过程得到一些论点.如果提供了足够数量的参数,它会将提供的参数传递给原始proc并返回结果.
这里要实现的关键点是零是splat参数的"足够数量的参数".
f = ->(x, y, z, *args){ [x, y, z, args] }
g = f.curry # => a "curryable" proc
h = g.call(1) # => another curryable proc
i = h.call(2) # => another curryable proc
j = i.call(3) # => [1, 2, 3, []]
Run Code Online (Sandbox Code Playgroud)
正如你所展示的那样,这些"可以理解"的过程可以一次一个地传递它们的参数,每次返回一个新的curryable过程,直到有足够的参数传递,此时它会进行评估.这也是他们不能支持任意长度的参数列表的原因 - 它如何知道何时停止currying并进行评估?
如果你想要一种允许任意数量的参数的不同的currying方式,你可以定义自己的curry方法:
def my_curry(f, *curried_args)
->(*args) { f.call(*curried_args, *args) }
end
Run Code Online (Sandbox Code Playgroud)
这是一个相当简单的实现,但可能符合您的目的.与内置方法的主要区别在于它总是返回一个新的proc,即使已经传递了足够的参数,并且它不支持一次一个"curry chaining".
f = ->(x, y, z, *args) { [x, y, z, args] }
g = my_curry(f, 1) # => a proc
g.call(2, 3) # => [1, 2, 3, []]
g.call(2, 3, 4, 5) # => [1, 2, 3, [4, 5]]
g.call(2) # => ArgumentError: wrong number of arguments (2 for 3)
h = my_curry(g, 2, 3) # => a proc
h.call # => [1, 2, 3, []]
h.call(4, 5) # => [1, 2, 3, [4, 5]]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1264 次 |
| 最近记录: |