forked from gnoack/fn
-
Notifications
You must be signed in to change notification settings - Fork 0
/
generators.fn
35 lines (33 loc) · 1.08 KB
/
generators.fn
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
;; Python-like generator functions.
;; Args:
;; yielder-proc: a proc accepting a yield argument.
;; Returns:
;; a get-next-value function, which will return values,
;; and finally raise stop-iteration.
(defn make-generator (yielder-proc)
(let ((suspended-caller nil)
(suspended-callee nil))
(defn generator ()
(yielder-proc yield)
(raise 'stop-iteration))
(defn yield (value)
(assert (nil? suspended-callee))
(set! suspended-callee (frame-caller ($get-frame)))
(set-frame-caller! ($get-frame) suspended-caller) ; return from get-next-value
(set! suspended-caller nil)
value)
(defn get-next-value ()
(unless (nil? suspended-caller)
(raise 'stop-iteration))
(set! suspended-caller (frame-caller ($get-frame)))
(when (nil? suspended-callee)
;; yield -- this also short-circuits back to the suspended caller
(generator))
(set-frame-caller! ($get-frame) suspended-callee) ; return from yield
(set! suspended-callee nil)
nil)
get-next-value))
(defn f123 (yield)
(yield 1)
(yield 2)
(yield 3))