From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: "John Wiegley" Newsgroups: gmane.emacs.devel Subject: Delimited continuations Date: Sat, 09 Dec 2017 01:06:23 -0800 Message-ID: NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: blaine.gmane.org 1512810442 23630 195.159.176.226 (9 Dec 2017 09:07:22 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Sat, 9 Dec 2017 09:07:22 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.90 (darwin) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Dec 09 10:07:18 2017 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eNb6L-0005zh-BR for ged-emacs-devel@m.gmane.org; Sat, 09 Dec 2017 10:07:17 +0100 Original-Received: from localhost ([::1]:40568 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eNb6S-0005u4-F2 for ged-emacs-devel@m.gmane.org; Sat, 09 Dec 2017 04:07:24 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:53000) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eNb6D-0005rS-2g for emacs-devel@gnu.org; Sat, 09 Dec 2017 04:07:09 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eNb68-0006Zk-4V for emacs-devel@gnu.org; Sat, 09 Dec 2017 04:07:09 -0500 Original-Received: from fencepost.gnu.org ([2001:4830:134:3::e]:58557) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eNb68-0006ZY-0f for emacs-devel@gnu.org; Sat, 09 Dec 2017 04:07:04 -0500 Original-Received: from auth2-smtp.messagingengine.com ([66.111.4.228]:36263) by fencepost.gnu.org with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.82) (envelope-from ) id 1eNb67-00034x-Oq for emacs-devel@gnu.org; Sat, 09 Dec 2017 04:07:03 -0500 Original-Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailauth.nyi.internal (Postfix) with ESMTP id 5B304209AB for ; Sat, 9 Dec 2017 04:07:01 -0500 (EST) Original-Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Sat, 09 Dec 2017 04:07:01 -0500 X-ME-Sender: Original-Received: from localhost (76-234-69-149.lightspeed.frokca.sbcglobal.net [76.234.69.149]) by mail.messagingengine.com (Postfix) with ESMTPA id ECEFC7E56E for ; Sat, 9 Dec 2017 04:07:00 -0500 (EST) Mail-Followup-To: emacs-devel@gnu.org X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2001:4830:134:3::e X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:220811 Archived-At: 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