Continued in general lisp on macros - regarding execution in OnLisp

In On Lisp , p. 267, Paul Graham provides an implementation of continue transmission macros:

(setq *cont* #'identity)

(defmacro =lambda (parms &body body)
  `#'(lambda (*cont* ,@parms) ,@body))

(defmacro =defun (name parms &body body)
  (let ((f (intern (concatenate 'string
                "=" (symbol-name name)))))
    `(progn
       (defmacro ,name ,parms
     `(,',f *cont* ,,@parms))
       (defun ,f (*cont* ,@parms) ,@body))))

(defmacro =bind (parms expr &body body)
  `(let ((*cont* #'(lambda ,parms ,@body))) ,expr))

(defmacro =values (&rest retvals)
  `(funcall *cont* ,@retvals))

t2 t1 , , , restart, , t1 A ( ) B ( ). restart, - *saved*, - dft-node (cdr tree) . =bind, =bind *cont*. *cont*, =bind , ?

(setq *saved* nil)

(=defun dft-node (tree)
    (cond ((null tree) (restart))
          ((atom tree) (=values tree))
          (t (push #'(lambda () (dft-node (cdr tree))) *saved*)
             (dft-node (car tree)))))

(=defun restart ()
    (if *saved*
        (funcall (pop *saved*))
      (=values 'done)))

(setq t1 '(a (b (d h)) (c e (f i) g))
      t2 '(1 (2 (3 6 7) 4 5)))

(=bind (node1) (dft-node t1)
  (if (eq node1 'done)
      'done
    (=bind (node2) (dft-node t2)
      (list node1 node2))))

(let ((*cont* (lambda (node1)
                (if (eq node1 'done)
                    'done
                    (let ((*cont* (lambda (node2)
                                    (list node1 node2))))
                      (dft-node t2))
  (dft-node t1))))))

(a 1). , restart (a 2) .. (a 5), (b 1), (b 2) .., , , (g 5):

> (let ((node1 (dft-node t1)))
    (if (eq? node1 ’done)done
        (list node1 (dft-node t2))))
(A 1)
> (restart)
(A 2)
> (restart)
(B 1)

(a 1) *cont*, let, . restart ? let restart? ?

+4
1

Lisp Common Lisp,

Lisp , Common Lisp , , On Lisp Common Lisp. CLiki . Lisp , , ( ):

(. 267) . Lisp. Lisp, . , . ( , #  # 'identity - ):

  • cont , let :
    ( defvar actual-cont # ')
    (define-symbol-macro * cont * * actual-cont *)
  • (setq * cont * # 'identity) (= somefun#' values ​​...)
  • ...

, , , . , :

  • 268 of < Lisp > ... comp.lang.lisp 2006 , (setq * cont *...) (defvar * cont *...). , On Lisp ANSI Common Lisp.

?

(= bind...) ( ((* cont *...))...), , * cont * - (.. ), , let, * cont *, , , . * cont * , :

CONTINUATIONS> (=bind (node1) (dft-node '(a (b (d h)) (c e (f i) g)))
                 (if (eq node1 'done)
                     'done
                     (=bind (node2) (dft-node '(1 (2 (3 6 7) 4 5)))
                       (list node1 node2))))
(A 1)
CONTINUATIONS> (restart)
2
CONTINUATIONS> (restart)
3
CONTINUATIONS> (restart)
6
CONTINUATIONS> (restart)
7
CONTINUATIONS> (restart)
4
CONTINUATIONS> (restart)
5
CONTINUATIONS> (restart)
B
CONTINUATIONS> (restart)
D

, (a 1) * * . - , , * cont *, , , # 'identity, = bind. 2, 3,... . * * - , B.

, (a 1), (a 2),..., (b 1) .. , , () , * cont * , .. . , * cont * ; , . Lisp, . 268:

*cont*, . *cont* , , : *cont* , =values , =defun. , add1 *cont* , . , , *cont* . *cont* setq defvar: .

Lisp Common Lisp, , Common Lisp , , (setq * cont *...) . Common Lisp . , , defparameter defvar, . , . , , , .

. , SBCL (setq *cont* …), ": undefined variable: CONTINUATIONS:: * CONT *" , * cont *, " (:: * CONT *), , ( * FOO *) ".

?

, , , , On Lisp:

(defparameter *restarts* '())

(defun do-restart ()
  (if (endp *restarts*) nil
      (funcall (pop *restarts*))))

(defun traverse-tree (k tree)
  (cond
    ((null tree) (do-restart))
    ((atom tree) (funcall k tree))
    (t (push (lambda () (traverse-tree k (cdr tree))) *restarts*)
       (traverse-tree k (car tree)))))

- * *. :

CL-USER> (traverse-tree 'identity '((1 2) (3 4)))
1
CL-USER> (do-restart)
2
CL-USER> (do-restart)
3
CL-USER> (do-restart)
4
CL-USER> (do-restart)
NIL

, , :

CL-USER> (let ((k (lambda (num)
                    (traverse-tree (lambda (alpha)
                                     (list num alpha))
                                   '(a (b) c)))))
           (traverse-tree k '((1 2) 3)))
(1 A)
CL-USER> (do-restart)
(1 B)
CL-USER> (do-restart)
(1 C)
CL-USER> (do-restart)
(2 A)
CL-USER> (do-restart)
(2 B)
CL-USER> (do-restart)
(2 C)
CL-USER> (do-restart)
(3 A)
CL-USER> (do-restart)
(3 B)
CL-USER> (do-restart)
(3 C)
CL-USER> (do-restart)
NIL

, * cont *, , let, .

, ( k , , , , gensym), , " = bind, .

+6

Source: https://habr.com/ru/post/1548243/


All Articles