Skip to content

Instantly share code, notes, and snippets.

@vseloved
Last active May 19, 2016 07:36
Show Gist options
  • Save vseloved/eafb2b3ab96f222c6e88d58af1374715 to your computer and use it in GitHub Desktop.
Save vseloved/eafb2b3ab96f222c6e88d58af1374715 to your computer and use it in GitHub Desktop.
Implement generator send with restarts
(define-condition generated ()
((item :initarg :item :reader generated-item)))
(defun yield (&optional item)
(restart-case (signal 'generated :item item)
(resume (&optional item) item)))
(defun send (item generator)
(let (already-triggered)
(handler-bind ((generated (lambda (e)
(declare (ignore e))
(when already-triggered
(return-from send))
(:= already-triggered t)
(invoke-restart (find-restart 'resume)
item))))))
(call generator))))
(defun get-data ()
(loop :repeat 3 :collect (random 10)))
(defun consume ()
(let ((running-sum 0)
(data-items-seen 0)
data)
(loop
(:= data (yield))
(:+ data-items-seen (length data))
(:+ running-sum (reduce '+ data))
(format t "Consumed ~A. The running average is ~A~%"
data (float (/ running-sum data-items-seen)))
(sleep 1))))
(defun produce ()
(loop
(let ((data (get-data)))
(format t "Produced ~A~%" data)
(send data 'consume))))
CL-USER> (produce)
Produced (0 3 7)
Consumed (0 3 7). The running average is 3.3333333
Produced (0 5 2)
Consumed (0 5 2). The running average is 2.3333333
Produced (9 8 3)
Consumed (9 8 3). The running average is 6.6666665
Produced (1 7 1)
Consumed (1 7 1). The running average is 3.0
Produced (1 6 8)
Consumed (1 6 8). The running average is 5.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment