要创建生成器函数,我们需要实现 yield(value)。 这将像 yield() 一样,但“值”将被传回并从 resume() 调用返回。
这将允许 range() 成为一个迭代器,而不是创建一个潜在的巨大数组。
这也将是迈向列表/字典理解等不错功能的一步。
不愉快的解决方法:
func xrange(count, dict):
var i = 0
while i < count:
dict.next = i
yield()
i += 1
func do_stuff():
var curr = {}
var it = xrange(5, curr)
while curr.value != null:
print(curr.value)
it.resume()
我刚刚开始使用 Godot(到目前为止喜欢它),但我同意它认为 yield() 应该能够返回比函数状态更多的东西。 Yield 就像返回具有 resume() 的能力,因此该函数应该能够通过屈服“返回”一个值。
我一直在考虑的一种可能的方法是增加 [GDScript]FunctionState
(https://docs.godotengine.org/en/3.1/classes/class_gdscriptfunctionstate.html)
有一个方法 value() 将参数返回给 yield()。
func co1():
yield(5)
s = co1()
print(s.value()) # prints 5
GDscript 已经有一个 yield ,它接受两个值并等待一个信号。 然而,这一个参数版本只会在 FunctionState 中返回它的参数。 只需进行该更改,生成器就可以编写为:
func xrange(count):
var i = 0
while i < count:
yield(i)
func do_stuff():
var it = xrange(5)
while it:
print(it.result())
it = it.resume()
这工作得很好,但有一个微妙之处值得考虑。 当协程函数返回(而不是产生)一个值而不是 FunctionState 时。 在上面的示例中,返回 null(因为函数是 void)我们测试它以停止 do_stuff() 中的循环。 如果协程函数返回一个值 [例如。 想象return false
在 xrange()] 的末尾,那么测试就会中断。
我想我会看看代码。
IMO,产量(价值)将是,呃,有价值的。
编辑:查看代码,yield 的信号版本存在复杂性,因此我在下面写的关于它的部分现在被删除。 以后可以细说。
yield
的工作方式存在一些问题,因此将其替换为更直接的await
。 我还不确定我们是否会做真正的发电机。
如果您仍然对添加生成器的想法感兴趣,请按照给定的问题模板在 GIP 跟踪器上打开一个新提案(在检查它不存在之后)。 大家可以参考这个issue,总结一下提案中的想法。 提前致谢!
最有用的评论
我刚刚开始使用 Godot(到目前为止喜欢它),但我同意它认为 yield() 应该能够返回比函数状态更多的东西。 Yield 就像返回具有 resume() 的能力,因此该函数应该能够通过屈服“返回”一个值。
我一直在考虑的一种可能的方法是增加 [GDScript]FunctionState
(https://docs.godotengine.org/en/3.1/classes/class_gdscriptfunctionstate.html)
有一个方法 value() 将参数返回给 yield()。
GDscript 已经有一个 yield ,它接受两个值并等待一个信号。 然而,这一个参数版本只会在 FunctionState 中返回它的参数。 只需进行该更改,生成器就可以编写为:
这工作得很好,但有一个微妙之处值得考虑。 当协程函数返回(而不是产生)一个值而不是 FunctionState 时。 在上面的示例中,返回 null(因为函数是 void)我们测试它以停止 do_stuff() 中的循环。 如果协程函数返回一个值 [例如。 想象
return false
在 xrange()] 的末尾,那么测试就会中断。我想我会看看代码。
IMO,产量(价值)将是,呃,有价值的。
编辑:查看代码,yield 的信号版本存在复杂性,因此我在下面写的关于它的部分现在被删除。 以后可以细说。