Talk:Call-with-current-continuation

From Wikipedia, the free encyclopedia

This article was originally based on material from the Free On-line Dictionary of Computing, which is licensed under the GFDL.

Contents

[edit] Rationale

This article does not address the issue of why call/cc was created, and what for... -- Karada 15:37, 5 March 2006 (UTC)

The rationale should be found in Continuation. --Kanjy 11:38, 7 March 2006 (UTC)

[edit] Inaccuracies and false claims

I have removed several inaccuracies and false claims, plus some awkward writing from this page.

I intend to elaborate on the logical implications of call/cc when I have time.

Matthias.f 15:06, 27 July 2007 (UTC)Matthias.f

[edit] Logging call/cc

It took me a while to figure out what was happening in the second example, leaving me with the impression that continuations are both:

a) A really clever idea that has expanded my understanding of what a program is.

b) Perhaps the most powerful program-obfuscation technique since self-modifying code.

In order to better understand them, I wrote the following. The first is a modification of call/cc that logs what is happening, and the second is a heavily annotated variant of the list-iteration example, in which I tried to separate each aspect of its use of continuations. I'm no Scheme programmer, and my experience of Lisp has been limited to a few weeks some years ago, but if they help, feel free to use them.

; A convenience function to apply 'display' to a list of items.
 
(define (displayList . items) (for-each display items))
 
 
; call-cc does what call/cc does, but displays what's going on before and after.
 
; 'toBeCalled' is the function that is to be called by call-with-current-continuation.
 
; If given, 'id' is a string (or whatever) that appears in every line that is
; displayed, so you can use it to tag each use of call-cc with a unique identifier,
; and therefore distinguish between them in the log.
 
(define (call-cc toBeCalled . id)
  ; The lambda expression allows me to display the continuation that is created here
  ; (the 'current continuation') before actually calling 'toBeCalled' with that
  ; continuation as its argument.
 
  ; 'return-value' captures the value that call-with-current-continuation returns, 
  ; so I can display it before returning it to the original caller.
 
  (let* (
         (tag (if (> (length id) 0) (car id) "?")) ; for when no id is given.
 
         (return-value (call-with-current-continuation 
                        (lambda (continuation) 
                          (displayList "call-cc of '" toBeCalled "' at '" tag 
                                       "' creates continuation " continuation "\n")
                          (toBeCalled continuation))))) ; the actual call-with-cc
 
    (displayList "\tcall-cc returned " return-value " to '" tag "'\n")
    return-value))
; Function make-yielding-iterator creates a closure such that each time function get-next
; is called, it returns the next element in the iteration over the given list.
 
; Get-next interacts with function yield, which is called in each pass of the  iteration.
; Yield stores the current list element in yielded-value, then calls a continuation that
; resumes in get-next; this then takes the saved value and returns it to its caller. When
; get-next is next called, it calls a continuation that resumes the iteration from where
; yield jumped out.
 
(define (make-yielding-iterator list)
  ; The initial values of these two variables are unimportant, as they are both reset
  ; before use.
 
  (define yielded-value #f)       ; The next element to be returned.
  (define return-to-get-next #f)  ; A continuation for returning control to get-next.
 
 
 
  ; resume-iteration (below) is the procedure to be called, by get-next, in order to
  ; resume iterating over the list. On all but the first use, we will want to resume
  ; from where we last yielded a value, but on the first call, we want to 'resume'
  ; by starting the iteration. Therefore, resume-iteration is initially defined as a 
  ; function for performing the iteration. Thereafter, each time yield returns control
  ; to get-next, resume-iteration is set to a continuation for resuming from where 
  ; the loop yielded, i.e. a continuation representing the remainder of the iteration.
 
  ; The first call of resume-iteration (via call/cc) also initializes return-to-get-next
  ; so that yield will return control to get-next.
 
  (define (resume-iteration get-next-continuation)
    (set! return-to-get-next get-next-continuation)
    (for-each yield list) ; The iteration itself.
    (yield #f))           ; Yield 'false' after we fall off the end of the list.
 
 
 
  ; The  functions get-next and yield call/cc each other alternately. They depend on
  ; the fact that when you call call/cc with a continuation as its argument, execution
  ; resumes where that continuation was created, and the thing returned there is a 
  ; continuation for resuming from where you came.
 
  (define (yield current-list-element)
    (set! yielded-value current-list-element) ; Save it, for get-next to return to the caller.
 
    ; Resume in get-next, giving it a continuation to come back here for the next iteration.
    ; When get-next returns here, it gives us a new continuation for going back to it next time.
 
    (set! return-to-get-next (call-cc return-to-get-next "yield")))
 
 
 
  (define (get-next)
    ; Resume in yield, giving it a continuation to come back here after the next iteration.
    ; When yield returns here, it gives us a new continuation for going back to it next time.
 
    (set! resume-iteration (call-cc resume-iteration "get-next"))
 
    yielded-value) ; Return the last-yielded value to the caller.
 
 
 
  ; 'Export' get-next by returning it from make-yielding-iterator
  ; (nothing else of this closure will be visible outside it.)
 
  get-next)   ; end of make-yielding-iterator
 
 
 
(define get-next-digit (make-yielding-iterator `(0 1 2 3 4 5 6 7 8 9)))
(define get-next-alpha (make-yielding-iterator `("a" "b" "c" "d" "e")))
 
(get-next-alpha) ; a
(get-next-digit) ;     0
(get-next-digit) ;     1
(get-next-alpha) ; b
(get-next-alpha) ; c
(get-next-digit) ;     2
(get-next-alpha) ; d
(get-next-digit) ;     3
(get-next-alpha) ; e
(get-next-digit) ;     4
(get-next-alpha) ; false
(get-next-digit) ;     5
(get-next-alpha) ; false

Raybo0 13:35, 19 September 2007 (UTC)

[edit] (call/cc (lambda (x) x)) is a no-op, right?

Mathias.f added the call to the first example: http://en.wikipedia.org/w/index.php?title=Call-with-current-continuation&oldid=147459612

And I took it out just now because I'm pretty sure it's redundant and not helpful in explaining the concept.

I'm a Lisp/Scheme n00b, but as I read it, it forms an anonymous function which invokes its only arg, then calls that anonymous function with the current continuation. The function invokes that continuation causing execution to continue where it 'left off'. If I'm wrong, the surrounding text should be edited to explain that line. Crag (talk) 02:35, 9 January 2008 (UTC)

Actually, in the line (display (call-with-current-continuation (lambda (x) x))) the lambda expression does not invoke the continuation, it simply returns it. However, I don't see what this line adds to the example, and I agree that this line should have been removed from the example. — Tobias Bergemann (talk) 07:41, 9 January 2008 (UTC)

as said above, it isn't a no-op. and it is demonstrating that you can get your hands on the continuation, as a first class, displayable object that you can sort of look at, which is something impossible in most languages. also, if you don't know what code does, and can't execute it to find out, you probably shouldn't be editing pages about it. so i put it back. —Preceding unsigned comment added by 67.177.213.111 (talk) 20:34, 21 January 2008 (UTC)

I don't see what this line adds to the example as the example doesn't show how the continuation is displayed, and the way continuations are displayed isn't specified in the Scheme standards anyway. Worse, it breaks the flow between the definition of f in the example and its use. Frankly, I find the line more confusing than enlightening and am tempted to remove it again or at least move it. —Tobias Bergemann (talk) 07:52, 22 January 2008 (UTC)
please move it - it's very confusing! I would do it myself, but I don't know what to say about it (and I don't want to just delete it because somebody tried that already and was undone). 149.159.72.139 (talk) 04:07, 30 January 2008 (UTC)

[edit] dynamic-wind, call-with-values, call-with-input-file etc.

The semantics of call/cc where changed with the move from R4RS to R5RS. Should the article explain the interaction between call/cc and dynamic-wind, call-with-values, call-with-input-file etc. (see e.g. Revised6 Report on the Algorithmic Language Scheme - Non-Normative Appendices - 11.9 Control features) or would this be too much detail? —Tobias Bergemann (talk) 09:41, 4 February 2008 (UTC)

IMO the article should be language-agnostic, considering that continuations aren't specific to Scheme. Obviously the fact that Scheme's call/cc was the original means that some implementation details might be interesting from a historical point of view, but otherwise I think it's irrelevant. Hairy Dude (talk) 23:50, 8 May 2008 (UTC)

[edit] Continuations as a generic control mechanism

Anecdotally, it's possible to code any pure Haskell monad using Cont (the continuation monad). Quick googling turned up this set of slides on the topic, though a proper paper would be nice. Hairy Dude (talk) 23:47, 8 May 2008 (UTC)