Groovy 非本地与本地回报:实施水平问题?

Groovy 非本地与本地回报:实施水平问题?,groovy,return,closures,smalltalk,Groovy,Return,Closures,Smalltalk,我最近玩了一点Groovy,惊讶地发现它不支持闭包内部的非本地返回。我对此感到非常惊讶,因为从Smalltalk发展到现在,我一直希望这是正常的情况。JDK8 lambdas也不支持非本地返回,因为我绝望地发现。幸运的是,Scala做到了 问题 要使关闭实现“成熟”,关闭内部的非本地返回是否必须?或者我只是习惯了Smalltalk,但事实并非如此 代码说明 def list = list(1, 2, 3) def value = list.forEach { each -> pri

我最近玩了一点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”,至少它不应该编译。

您想要的是代替

def list=[1,2,3]
def value=list.findResult{each->
println(每个)
如果(每个)
返回每个
返回5
}
println(值)
//印刷品11

找不到支持我的数据,但这里是我的0.02:闭包只能从自身返回,而不能从父调用方返回。父调用方的返回与ruby的块(1)中使用的概念相同:两个块(被调用方和调用方)的控制/作用域是相同的,而闭包应该是独立的

在groovy中这样做的关键是一个syntactic sugar,通过抛出异常从闭包中“返回”

要在groovy中从闭包中“返回”,请坚持使用或
findResult
(根据@jesseplymeal的回答):这些元素在右侧元素中迭代

我不是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,带块和lambda:

# 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的大师,这可能或多或少是错误的。

我也会投入我的两分钱。我不认为是什么让关闭比另一个更成熟,有一个明确的答案。但是

我认为说闲话的人对他们的关闭感到非常自豪(这是理所当然的)。我曾经听说“Smalltalk blocks对lambda的贡献大于其他任何lambda运动语言。”


大多数语言参考都有一节专门讨论“流控制”。但Smalltalk是我所知道的唯一一种不仅敢于“一路向下”处理对象,而且敢于“一路完成闭包”的语言。Smalltalk中的所有流控制(循环、逻辑分支等)都是用闭包完成的(或者至少看起来是这样,不要注意幕后的优化编译器!)带有本地返回的词法闭包是实现lambdas最常用的方法。 实际上,Smalltalk/Ruby块中的非本地返回是大多数其他语言的例外。 有些Smalltalk甚至没有真正关闭词法范围内的块,因此您可能会质疑块在多大程度上可以被视为闭包

如果你像我一样从Scheme转到Smalltalk/Ruby,你的问题可能正好相反。也就是说:“Smalltalk街区是否应将其本地返回视为‘全轮廓封闭’?”

即:非局部返回(主要)是为了简化处理控制结构,但它是一种特殊的机制。您可以将其称为转义继续,其中执行流转义或跳到另一个点

非局部返回不是闭包不可分割的一部分,只是一种特殊情况,可以独立实现(具体化的延续、异常、其他特殊构造)

见这篇(旧)文章:

下面是关于闭包和返回的相关讨论:

[编辑]

发现此相关问题:


问题到底是什么?有些人会同意你,有些人不会。你会得到什么?如果你认为这是Groovy的一个阻塞点,那么就不要使用它。允许访问自由变量的表达式是否已经是闭包?或者它是否需要支持非本地返回以避免“伪造”闭包?因此Groovy确实支持findResult方法中的非本地返回。这是个好消息。尽管如此,我显示的代码应该按照预期工作,或者不应该编译。所以我真的不确定降级到底是为了什么。不管怎么说,问题是什么可以弥补结束。非本地回报是否是一个实质性问题,如果没有这个问题,关闭就不是一个“真正的”关闭,还是更准确?想知道是否有任何关于闭包的定义。我在网上发现的东西很模糊。。。谢谢,OliverThis Scala代码可以编译,但也可以按预期打印“11”:对象Foo{def main(args:Array[String]){println(bar)}def bar:Int={val list=list(1,2,3)list.foreach{each=>if(true){return each}5}@OliverFlow Groovy的每个都将继续,直到所有元素都被迭代。所以你的论点实际上是关于
each
vs
foreach
,而不是闭包本身。@TimYares:谢谢,Tim。但我不明白你的意思。集合中似乎没有foreach迭代器,也不是作为语言关键字。你是说一个普通的f吗或者循环?另一件我不明白的事情是,为什么可以从findResult中返回,但不能从forEach中返回。所以整个问题都与闭包无关?!我现在有点困惑……非常感谢,威尔。我用Scala写了同样的东西,很高兴Scala的行为与我在Smalltalk中习惯的方式相同。真的不很高兴看到Scala只会抛出一个异常来进行非本地返回。但这是一个很好的信息!我想知道这是否是JVM引起的…我想是的。我认为大多数闭包/lambdas/SAMs都是使用匿名类实现的,而不是真正的循环。也许如果编译器能够将其变成一个方法…维基百科说关于本地v的几句话
# 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
})