Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python generators in various languages [closed]

How do you emulate Python style generators in your favorite language? I found this one in Scheme. It must be interesting to see other implementations, especially in those languages that don't have first-class continuations.

like image 323
Vijay Mathew Avatar asked Sep 20 '09 15:09

Vijay Mathew


1 Answers

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 i

for 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.

like image 86
Rainer Joswig Avatar answered Sep 20 '22 00:09

Rainer Joswig