Python generators in various languages [closed] Python generators in various languages [closed] python python

Python generators in various languages [closed]


I wouldn't use yield at all in Lisp/Scheme.

'yield' requires some kind of co-routine or continuation facility in the language. Many uses of yield can be implemented in a simpler functional way.

YIELD is basically related to the famous COME-FROM operator. ;-) Here, a call in some place can lead to different places in some other routine, depending on its execution context. So a routine suddenly has multiple entry points whose order is determined at runtime. For simple uses this may be fine, but I would argue that for more complex code reasoning about the code would get harder.

Take the Scheme example linked in the question:

(define/y (step)   (yield 1)  (yield 2)  (yield 3)  'finished)(list (step) (step) (step))

Calling (step) multiple times returns different values then.

I would just create a closure:

(define step  (let ((state '(1 2 3 finished)))    (lambda ()      (pop state))))

This breaks above function with a yield into two different things: a variable that carries the state and a simple function that changes the state. The state is no longer implicitly coded into the execution sequence.

 (list (step) (step) (step))))

One can imagine similar solutions for other uses of yield.

Compare that with the generators from the Common Lisp SERIES library:

(let ((x (generator (scan '(1 2 3 finished)))))  (list (next-in x)        (next-in x)        (next-in x)))

If we look at this Python example from another answer

def simpleRange(n):    for i in xrange(n):        yield ifor n in simpleRange(5):     print(n)

we can see that it duplicates the control structure. Both the calling place and the generator use a FOR iteration control structure. Using closures, we can get rid of the use of control structures inside the generator, by only providing the state transition code.


Here is an example in C++ that simulates generators using fibers:

Yield Return Iterator for Native C++ Using Fibers

The "yield return" iterator is a language feature that was created for one reason: simplicity. It is generally much easier to iterate across whole collectionl, storing all context needed in local variables, rather than crafting a complicated, custom iterator object that stores its state across subsequent retrieval operations.

There are also the primitive C routines setjmp, longjmp to achieve similar results.
(Lua coroutines are implemented with the above method)


In JavaScript 1.7+ I usually only have to add a few parentheses and brackets. Everything else is about the same. JavaScript 1.7 introduced pythonic generators and iterators among other things.

Generator expressions:

# Python(x + 1 for x in y if x > 100)// JavaScript 1.8+(x + 1 for (x in y) if (x > 100))

Generators

# Pythondef simpleRange(n):    for i in xrange(n):        yield ifor n in simpleRange(5):     print(n)// JavaScript 1.7+function simpleRange(n) {    for (let i = 0; i < n; i++)        yield i;}for (n in simpleRange(5))    print(n);

List/Array comprehensions

# Python[x + 1 for x in y if x > 100]// JavaScript 1.7+[x + 1 for (x in y) if (x > 100)]