Is this expected output for call-with-composable-continuation?

#lang racket/base
(let ([tag (make-continuation-prompt-tag)])
	(println "111")
	(println (string-append "222"
		(call-with-continuation-prompt
			(lambda ()
				(let ([data 0])
					(println (string-append "333"
						(call-with-composable-continuation
							(lambda (k)
								(println "---")
								(println (string-append "pop& " (k " push&")))
								"666")
							tag)))
					(println (string-append "zzz"
						(call-with-composable-continuation
							(lambda (k)
								(println "+++")
								(println (string-append "pop| " (k " push|")))
								"ddd")
							tag)))
					(println data)
					(set! data (+ data 1))
					(if (= data 56) ;; Have to do this since infinite loop
						(abort-current-continuation tag "bbb")
						"777")))
			tag
			(lambda (k)
				(println (string-append "888" k))
				"aaa"
				)))))
	(println "999")

It weird that push& and pop& does not paired, I would expect both to appear only once. Am I missing something, or did I misunderstood how call-with-composable-continuation works?

1 Like

With composable continuations, you can literally calculate out the result. For example, the first call-with-composable replaces k with

(lambda (x) 
  (let ([data 0])
    (println (string-append "333" x))
    (println (string-append "zzz"
                            (call-with-composable-continuation
                             (lambda (k)
                               (println "+++")
                               (println (string-append "pop| " (k " push|")))
                               "ddd")
                             tag)))
    (println data)
    (set! data (+ data 1))
    (if (= data 56) ;; Have to do this since infinite loop
        (abort-current-continuation tag "bbb")
        "777")))

You can plug this expression in (substitute for) k and continue calculating with ordinary functional laws. (It is the inner call-with-composable that causes the “infinite” loop.) If you change the 56 to something sensible at first, say 2, you can see it all unfold. When you encounter a printf just write down the result on the side.

(I’d be surprised if this expression represents a bug in racket/control; the first call looks all okay.)

1 Like

Hm like this right?

#lang racket/base
(let ([tag (make-continuation-prompt-tag)])
	(println "111")
	(println (string-append "222"
		(call-with-continuation-prompt
			(lambda ()
				(let ([data 0])
					(println (string-append "333"
						(begin
							(println "---")
							(println (string-append "pop& " ((lambda (x)
								(println (string-append "333" x))
								(println (string-append "zzz"
									(call-with-composable-continuation
										(lambda (k)
											(println "+++")
											(println (string-append "pop| " (k " push|")))
											"ddd")
										tag)))
								(println data)
								(set! data (+ data 1))
								(if (= data 56) ; Have to do this since infinite loop
									(abort-current-continuation tag "bbb")
									"777")) " push&")))
							"666"
						))))
				"777")
			tag
			(lambda (k)
				(println (string-append "888" k))
				"aaa"
				)))))
	(println "999")

However it seems like the behavior is too different as the code no longer stuck in recursive loop (as this looks like almost the same behavior when change 56 to 2) unless I missed something obvious during transformation.