如何用您喜欢的语言模拟Python样式生成器?我在Scheme中找到了这个.看到其他实现一定很有趣,特别是那些没有一流延续的语言.
我不会在Lisp/Scheme中使用yield.
'yield'需要某种语言的常规或继续设施.可以以更简单的功能方式实现产量的许多用途.
YIELD基本上与着名的COME-FROM运算符相关.;-)在这里,某个地方的调用可能会导致某些其他例程中的不同位置,具体取决于其执行上下文.因此,例程突然有多个入口点,其顺序在运行时确定.对于简单的用途,这可能没问题,但我认为对于更复杂的代码,对代码的推理会变得更难.
以问题中链接的Scheme示例为例:
(define/y (step) (yield 1) (yield 2) (yield 3) 'finished) (list (step) (step) (step))
多次调用(步骤)会返回不同的值.
我只想创建一个闭包:
(define step (let ((state '(1 2 3 finished))) (lambda () (pop state))))
这打破了上面的功能,产生了两个不同的东西:一个携带状态的变量和一个改变状态的简单函数.状态不再隐式编码到执行序列中.
(list (step) (step) (step))))
人们可以想象其他产量用途的类似解决方案.
将它与Common Lisp SERIES库中的生成器进行比较:
(let ((x (generator (scan '(1 2 3 finished))))) (list (next-in x) (next-in x) (next-in x)))
如果我们从另一个答案看这个Python示例
def simpleRange(n): for i in xrange(n): yield i for n in simpleRange(5): print(n)
我们可以看到它复制了控制结构.调用位置和生成器都使用FOR迭代控制结构.使用闭包,我们可以通过仅提供状态转换代码来摆脱生成器内部控制结构的使用.
以下是C++中使用光纤模拟生成器的示例:
使用光纤的Native C++的Yield Return Iterator
"yield return"迭代器是一个语言功能,其创建原因有以下几点:简单性.迭代整个集合通常要容易得多,存储局部变量中所需的所有上下文,而不是制作一个复杂的自定义迭代器对象,该对象在后续检索操作中存储其状态.
还有原始的 C例程setjmp,longjmp可以实现类似的结果.
(Lua 协程用上面的方法实现)