`

curry和闭包封装参数的区别

阅读更多
from: http://hamletdarcy.blogspot.com/2008/01/curry-vs-closure-wrapping-in-groovy.html

这篇文章讲了使用curry来bind参数和使用闭包bind参数的一些区别, 觉得对理解curry和闭包不错, 简单的翻译了下

首先是一个例子:
def concat = { x, y ->
 x + delegate.call() + y
}

concat.delegate = { " " }

assert concat("Hello", "World") == "Hello World"

注意delegate.call()的用法, 这里的delegate可以看成是一个变量, 可以随时在调用concat前进行修改, 比如用逗号, 分号来分隔

在大多数情况使用curry和使用闭包的效果是一样的.

比如在curry中可以这样写:
def hello = concat.curry("Hello")
assert hello("World") == "Hello World"


使用闭包可以这样写:
def hello = { x -> concat("Hello", x) }
assert hello("World") == "Hello World"


二者稍微有些区别, 在curry中定义的hello是CurriedClosure的实例, 而第二个hello是Closure的实例, 当然还有一个区别是curry绑定的参数是从左到右的(现在的rcurry, ncurry可以解决参数的顺序问题), 而使用闭包则相对灵活些.

这里我要说的是他们在对待delegate这个分隔符的区别.
对于curry, 效果是这样的:
def hello = concat.curry("Hello")
hello.delegate = { "," }
assert hello("World") == "Hello,World"


而对于闭包, 效果却是这样的:
def hello = { x -> concat("Hello", x) }
hello.delegate = { "," }
assert hello("World") == "Hello World"


出现不同的结果的解释是: 对于curry来说, 得到的CurriedClosure可以认为是对原有的concat闭包的一个继承, 因此得到的hello可以使用delegate, 而对于闭包来说, 是使用了一个新的闭包hello来包装了concat闭包, 因此hello就无法获取contat的delegate了
分享到:
评论
2 楼 macrochen 2010-10-22  
JohnnyJian 写道
引用
concat.delegate = { " " }

像这样子修改闭包的delegate我觉得是不值得推荐的,因为delegate有特殊的语义(在闭包中找不到的方法和变量会在delegate中查找)。
这里应该用一个参数来表示连接符,而不是通过delegate。

估计作者只是用这个例子来说明它的观点, 而实际应用中通过参数的方式可能更合适
1 楼 JohnnyJian 2010-10-21  
引用
concat.delegate = { " " }

像这样子修改闭包的delegate我觉得是不值得推荐的,因为delegate有特殊的语义(在闭包中找不到的方法和变量会在delegate中查找)。
这里应该用一个参数来表示连接符,而不是通过delegate。

相关推荐

Global site tag (gtag.js) - Google Analytics