Execute the following call/cc expression

孤人 提交于 2020-01-14 04:34:27

问题


I use racket and I got the result 4 for following simple code:

(let/cc done
  ((let/cc esc
     (done (+ 1 (let/cc k
                  (esc k)))))
   3))

and I was going to execute this code step-by-step.

First, I changed the first let/cc into the form of call/cc like below:

(call/cc (λ (done)
           ((let/cc esc
              (done (+ 1 (let/cc k
                           (esc k)))))
            3)))

Of course, this produces 4 also.

Second, since I found the mechanism of call/cc in the internet which says call/cc do following 4 steps:

  1. Captures the current continuation.
  2. Constructs a function C that takes one argument, and applies the current continuation with that argument value.
  3. Passes this function as an argument to expr --- i.e., it invokes (expr C).
  4. Returns the result of evaluating (expr C), unless expr calls C, in which case the value that is passed to C is returned.

Thus, I followed above steps for the first call/cc like:

  1. Current continuation is an identity.
  2. C refers (λ (x) x).
  3. Since expr is (λ (done) ((let/cc esc (done (+ 1 (let/cc k (esc k))))) 3)), (expr C) is:

    ((λ (done)
       ((let/cc esc
          (done (+ 1 (let/cc k
                       (esc k)))))
        3))
     (λ (x) x))
    
  4. To return the result value of above code, I execute above in racket.

But, above code (modified by me) is not executed and produces an error:

> application: not a procedure;
>
> expected a procedure that can be applied to arguments
>
>  given: 4
>
>  arguments...:
>
>   3

Please what I did wrong. I'm confusing the concept of continuation. Thanks.


回答1:


Continuations are not just closures (functions). They also perform a jump to their defining location in code. You have to perform the CPS transformation in full to try evaluating the resulting expression in Scheme interpreter. That expression will only contain lambdas and no continuations (in the sense of call/cc (1)).

The expression that you tried mixes them both - it defines done as simple lambda-defined function, but it is still used in the nested context as a continuation.


(1) (another source of confusion is calling the function arguments in the continuation-passing style "continuations". they are not "true" continuations; they are simple functions "to be called" in this or that eventuality, so colloquially they are also referred to as "continuations" although "contingencies" or even "handlers" could be better.)

See also another example of call/cc code translation.

Following that approach, translating your Scheme code into Common Lisp, we get:

;; (let/cc done
;;   ((let/cc esc
;;      (done (+ 1 (let/cc k
;;                   (esc k)))))
;;    3)) 
(prog  (retval done arg1 func esc arg2 k arg3 arg4)
    (setq done (lambda (x) (setq retval x) (go DONE)))    ; 3
     (setq arg1 3)                                        ; 5
      (setq esc  (lambda (x) (setq func x) (go ESC)))     ; 8
       (setq arg3 1)                                      ; 10
        (setq k  (lambda (x) (setq arg4 x) (go K)))       ; 12
        (setq arg4 (funcall esc k))                       ; 13
  K                                                       ; 11  continuation K
       (setq arg2 (+ arg3 arg4))                          ; 9
      (setq func (funcall done arg2))                     ; 7
  ESC                                                     ; 6   continuation ESC
     (setq retval (funcall func arg1))                    ; 4
  DONE                                                    ; 2   continuation DONE
    (return retval))                                      ; 1

which indeed returns 4 (the lines of code are numbered in order as they are written, during the translation).




回答2:


When the interpreter sees a call/cc even the interpreters that doesn't do CPS does it with that subtree. Your code would look something like this:

((λ (done)
   ((λ (esc)      
      ((λ (k) (esc k))
       (λ (r) (k+ done 1 r))))
    (λ (v) (v 3))))
 values)


; k+ implementation (+, but CPS) 
(define (k+ k . args)
  (k (apply + args)))


来源:https://stackoverflow.com/questions/34299077/execute-the-following-call-cc-expression

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!