我最近在Groovy上玩了一下,并且惊讶地发现它不支持闭包内部的非本地返回。我对此感到非常惊讶,因为我一直认为这是使用Smalltalk开发时的正常情况。当我想到绝望时,JDK8 lambdas也不支持非本地回报。令人高兴的是,Scala确实如此。
问题 封闭实现中的非本地返回是否必须是“完全成熟”的闭包实现?或者我只是从Smalltalk习惯了,但不一定是这样。
代码插图
def list = list(1, 2, 3)
def value = list.forEach { each ->
println(each)
if(true)
return each
return 5
}
println(value)
我希望它打印“11”而不是“1235”。如果它打印“1235”,至少它不应该编译。
答案 0 :(得分:1)
您想要的是list.findResult()而不是list.each()。
def list = [1, 2, 3]
def value = list.findResult { each ->
println(each)
if(each)
return each
return 5
}
println(value)
// prints 1<newline>1
答案 1 :(得分:1)
发现没有数据支持我,但这里是我的0.02:一个闭包只能从它自己返回,而不是从父来电者返回。来自父调用者的返回与ruby的块(1)中使用的概念相同:两个块(被调用者和调用者)的控制/范围是相同的,而闭包应该是独立的。
执行它的scala way是在groovy中执行它的一个合成糖:通过抛出异常从闭包中“返回”。
要从groovy的闭包中“返回”,请坚持find
, findAll
或findResult
(根据@ jesseplymale的回答):这些正在遍历正确的元素。
...
我不是javascript的大师,但他似乎同意我的意见:
// prints every item; the return is only from the function
[1, 2, 3, 4, 5].forEach( function(item) {
console.log(item);
return item;
})
Ruby,包含块和lambdas:
# block: prints "1" and stop iterating
def a()
[1, 2, 3, 4, 5].each { |it|
puts it
return it
}
end
a()
传递一个块和一个lambda作为参数:
# this method receives a block/lambda and passes
# it to the 'each' method from list
def b(block)
[1, 2, 3, 4, 5].each &block
end
# this block fails with "unexpected return (LocalJumpError)"
#b(Proc.new { |it| puts it; return it; })
# this lambda keeps iterating and printing, even though
# it has the return statement
b(lambda { |it|
puts it
return it
})
(1):注意我不是Ruby中的大师,这可能或多或少是错误的。
答案 2 :(得分:1)
我也会把我的两分钱扔进去。我认为没有一个明确的答案可以使封口比另一种更完整。但...
我认为Smalltalkers对他们的封闭感到非常自豪(理所当然)。我曾经听说过“Smalltalk积木为lambda的事业做的比其他任何一种运动语言都要多。”
大多数语言参考都有一节专门讨论“流量控制”。但Smalltalk是我所知道的唯一一种不仅要做“对象一直向下”而且“一直关闭”的语言。 Smalltalk中的所有流控制(循环,逻辑分支等)都是通过闭包完成的(或者至少看起来这样做,不关注幕后优化编译器!)。
答案 3 :(得分:0)
本地返回的词法结束是实现lambda的最常用方法。 实际上,Smalltalk / Ruby块中的非本地返回是大多数其他语言的例外。 一些Smalltalks甚至没有真正关闭块而不是词法范围,所以你可能会质疑块可以被认为是闭包的程度。
如果你从Scheme转到Smalltalk / Ruby(就像我一样),你的问题可能恰恰相反。即:“Smalltalk区块是否应该将本地回报视为'全程关闭'?”
即:非局部返回(大部分)是为了简化处理控制结构,但它是一种特殊的机制。您可以将其称为转义延续,其中执行流程会转义或跳转到另一个点。
非本地回报不是闭包的组成部分,只是一个特例,可以独立实现(具体化的延续,例外,其他特殊结构)。
请参阅此(旧)文章:http://smalltalk.gnu.org/blog/s11001001/lexical-block-return-language-crux
以下是有关闭包和退货的相关讨论:http://lambda-the-ultimate.org/node/2009
[编辑]
发现此相关问题:
Exactly what is the difference between a "closure" and a "block"?