2

Both of the following code blocks should (in my mind) be infinite loops

This works

(define call/cc call-with-current-continuation)

(define l 0)
(define i 0)

((lambda ()
   (call/cc
    (lambda (k)
      (set! l k)))
   (write i)
   (newline)
   (set! i (+ i 1))
   (l "ignore")))

This does not work:

(define call/cc call-with-current-continuation)

(define l 0)
(define i 0)

(begin
   (call/cc
    (lambda (k)
      (set! l k)))
   (write i)
   (newline)
   (set! i (+ i 1))
   (l "ignore"))

The only difference is one uses a lambda and one uses a begin block. Why does the second block of code not work?

Thanks

timkomip
  • 45
  • 4

1 Answers1

6

In the second case, the begin splices its arguments into the top-level. Note that there are two kinds of begin: if it's in an expression position, it just sequences operations one after the other. The second kind (which is what you have) will splice all of its arguments into the surrounding context.

The spliced call/cc expression's continuation is actually the empty continuation, since each top-level expression is evaluated separately (i.e., in the empty continuation). You can check this by putting a let around the begin, which forces it to be in an expression position. Then it will infinite loop like you expect.

Asumu Takikawa
  • 8,447
  • 1
  • 28
  • 43
  • 1
    Thanks! Also, what is meant by "will splice all of its arguments into the surrounding context"? – timkomip Apr 17 '13 at 00:08
  • 1
    (begin (begin 1) (begin 2 3) (begin 4)) will expand to (begin 1 2 3 4). The content of the inner begins are "spliced" into the context of the outer begin. – soegaard Apr 17 '13 at 12:35