[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Delimited continuations
From: |
John Wiegley |
Subject: |
Delimited continuations |
Date: |
Sat, 09 Dec 2017 01:06:23 -0800 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/26.0.90 (darwin) |
It just occurred to me this evening that lexical-binding makes delimited
continuations (https://en.wikipedia.org/wiki/Delimited_continuation) trivial
to implement in Emacs Lisp:
;; -*- lexical-binding: t -*-
(defun shift (k entry)
(if (eq (nth 0 k) 'outer)
(throw (nth 1 k)
(funcall entry #'(lambda (val)
(funcall (nth 2 k)
(list 'inner val)))))
(nth 1 k)))
(defun reset (thunk)
(let ((bound (make-symbol "reset--bound")))
(catch bound
(funcall thunk (list 'outer bound thunk)))))
(reset
#'(lambda (_)
(+ 4 (reset
#'(lambda (p)
(* 2 (shift p #'(lambda (k)
(funcall k (funcall k 4))))))))))
;; (+ 4 (* 2 (* 2 4)))
;; => 20
(reset
#'(lambda (q)
(+ 4 (reset
#'(lambda (_)
(* 2 (shift q #'(lambda (k)
(funcall k (funcall k 4))))))))))
;; (+ 4 (* 2 (+ 4 (* 2 4))))
;; => 28
This can handy when coding something that naturally lends itself to "inversion
of control", when it's easier to code the inner structure of something up
front, and then refer to that structure -- possibly repeating it and
transforming it -- to build up the resulting data:
(let ((data '(1 2 3)))
(reset
#'(lambda (p)
(list 'a 'b (shift p #'(lambda (k)
(append (funcall k 0)
(mapcar (apply-partially k)
data))))))))
;; => (a b 0
;; (a b 1)
;; (a b 2)
;; (a b 3))
--
John Wiegley GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com 60E1 46C4 BD1A 7AC1 4BA2