【发布时间】:2011-01-09 09:44:25
【问题描述】:
是否可以在 Scala 中实现与 Python yield 语句等效的功能,在该语句中,它会记住使用它的函数的本地状态并在每次调用时“生成”下一个值?
我想要有这样的东西来将递归函数转换为迭代器。有点像这样:
# this is python
def foo(i):
yield i
if i > 0:
for j in foo(i - 1):
yield j
for i in foo(5):
print i
除了,foo 可能更复杂,并通过一些非循环对象图递归。
其他编辑: 让我添加一个更复杂的示例(但仍然很简单): 我可以编写一个简单的递归函数来打印东西:
// this is Scala
def printClass(clazz:Class[_], indent:String=""): Unit = {
clazz match {
case null =>
case _ =>
println(indent + clazz)
printClass(clazz.getSuperclass, indent + " ")
for (c <- clazz.getInterfaces) {
printClass(c, indent + " ")
}
}
}
理想情况下,我希望有一个库,可以让我轻松更改一些语句并将其用作迭代器:
// this is not Scala
def yieldClass(clazz:Class[_]): Iterator[Class[_]] = {
clazz match {
case null =>
case _ =>
sudoYield clazz
for (c <- yieldClass(clazz.getSuperclass)) sudoYield c
for (c <- clazz.getInterfaces; d <- yieldClasss(c)) sudoYield d
}
}
似乎延续允许这样做,但我只是不明白shift/reset 的概念。 continuation 最终会进入主编译器吗?是否有可能提取出库中的复杂性?
编辑 2: 在另一个线程中检查Rich's answer。
【问题讨论】:
-
很难想出一个无法通过标准技术实现的易于处理的示例。例如,我认为您的
yieldClass示例可以通过巧妙地使用Iterator.++来实现。但是,是的,我认为yieldClass可以在移位/重置方面实现。我不知道它什么时候会在不需要插件的情况下进入编译器。我认为大多数复杂性都可以分解为“生成器库”。我认为 Rich Dougherty 的博客是这些小动物的最佳解释来源。 -
您对 Iterator.++ 的看法是正确的。 gist.github.com/286682 有效。我得去看看 Rich 的博客。
-
这是一个副本,但奇怪的是,我没有在“相关”中看到原件。
-
抱歉 OT,但我盯着你的 sudoYield 看了一会儿,直到我意识到你可能指的是 pseudoYield。伪=假的或假装的; sudo = 超级用户做(一个 linux 命令)。看到这个:dictionary.reference.com/browse/pseudo 这个:xkcd.com/149