What is reason for callcc{|c|c}?

Discussion in 'Ruby' started by John Carter, Mar 6, 2005.

  1. John Carter

    John Carter Guest

    The excellent article in callcc at
    http://www.all-thing.net/Ruby/iterators_generators_and_continuations_in_ruby.html

    makes the following statement...

    The way to create a continuation is with Kernel#callcc. For what I
    imagine are historical reasons, the continuation is passed as an
    argument to a block, rather than returned directly. So the idiom to get
    a continuation at the current point in the code is this:

    c = callcc { |c| c }

    Can anyone elaborate on this history?

    Or is there a deeper reason than mere history?

    Because I find it very confusing.

    Thanks


    John Carter Phone : (64)(3) 358 6639
    Tait Electronics Fax : (64)(3) 359 4632
    PO Box 1645 Christchurch Email :
    New Zealand

    Refactorers do it a little better every time.
     
    John Carter, Mar 6, 2005
    #1
    1. Advertising

  2. John Carter wrote:
    > The excellent article in callcc at
    > http://www.all-thing.net/Ruby/iterators_generators_and_continuations_in_ruby.html
    >
    >
    > makes the following statement...
    >
    > The way to create a continuation is with Kernel#callcc. For what I
    > imagine are historical reasons, the continuation is passed as an
    > argument to a block, rather than returned directly. So the idiom to get
    > a continuation at the current point in the code is this:
    >
    > c = callcc { |c| c }
    >
    > Can anyone elaborate on this history?
    >
    > Or is there a deeper reason than mere history?


    Two reasons, neither particularly historical, come to mind:

    1. So you can implement throw/catch-style control structures.

    2. So a result can be passed to the continuation.

    Both are illustrated by:

    p callcc { |c|
    c.call "result"
    puts "don't get here"
    }
    puts "got here"

    Output:

    "result"
    got here
     
    Joel VanderWerf, Mar 6, 2005
    #2
    1. Advertising

  3. Joel VanderWerf wrote:
    > 2. So a result can be passed to the continuation.


    Duh. Of course you can do that with

    c = callcc { |c| c }

    as the article says. The first time through, the value assigned to c
    will be the continuation. The second time (after c.call(x)), the value
    assigned to c will be arg x.
     
    Joel VanderWerf, Mar 6, 2005
    #3
  4. John Carter ha scritto:

    >
    > Can anyone elaborate on this history?


    call-with-current-continuation in scheme works like this, passing the
    c.c. to a function, and ruby follows this tradition.
     
    gabriele renzi, Mar 6, 2005
    #4
  5. John Carter

    Csaba Henk Guest

    On 2005-03-06, John Carter <> wrote:
    > c = callcc { |c| c }
    >
    > Can anyone elaborate on this history?
    >
    > Or is there a deeper reason than mere history?


    Of course, this blocky form is useful (as it's with blocky forms in ruby
    usually).

    But I think it should be allowed to have a plain "callcc" which would
    be equivalent with today's "callcc { |c| c }".

    You can just do

    module Kernel
    alias call_with_current_continuation callcc

    def callcc(*a,&b)
    b ||= proc{ |c| c }
    call_with_current_continuation(*a,&b)
    end
    end

    Just like with fork, but the other way around:

    traditional unix-style fork works like:

    if pid = fork
    # parent code...
    else
    # child code...
    end

    (this is the way we'd like to have with callcc)
    and ruby introduced the blocky form

    fork { #child code }; #parent goes on...

    but the traditional style fork remained valid.

    As a sidenote: with cvs ruby you can do the following:

    if pid = callcc { |c| fork{c.call} }
    # parent
    else
    # child
    end

    That is, traditional fork style can be defined in terms of blocky fork,
    thanks to callcc. This might come handy if you bump into some fork
    wrapper which supports only the blocky form (imagine, eg., some
    pty_fork, which doesn't have proper implementation in current ruby).

    Csaba


    Csaba
     
    Csaba Henk, Mar 7, 2005
    #5
  6. John Carter

    Luke Graham Guest

    The block usually wants to return a useful value itself.


    On Mon, 7 Mar 2005 08:16:17 +0900, Joel VanderWerf
    <> wrote:
    > Joel VanderWerf wrote:
    > > 2. So a result can be passed to the continuation.

    >
    > Duh. Of course you can do that with
    >
    > c = callcc { |c| c }
    >
    > as the article says. The first time through, the value assigned to c
    > will be the continuation. The second time (after c.call(x)), the value
    > assigned to c will be arg x.
    >
    >



    --
    spooq
     
    Luke Graham, Mar 7, 2005
    #6
  7. Luke Graham wrote:
    > The block usually wants to return a useful value itself.
    >
    >
    > On Mon, 7 Mar 2005 08:16:17 +0900, Joel VanderWerf
    > <> wrote:
    >
    >>Joel VanderWerf wrote:
    >>
    >>>2. So a result can be passed to the continuation.

    >>
    >>Duh. Of course you can do that with
    >>
    >> c = callcc { |c| c }
    >>
    >>as the article says. The first time through, the value assigned to c
    >>will be the continuation. The second time (after c.call(x)), the value
    >>assigned to c will be arg x.



    Just to clarify, this is how c can be assigned a return value other than
    the continuation:

    c = callcc { |c| c }
    p c
    c.call(3) if c.respond_to?:)call)

    Output is:

    #<Continuation:0xb7e51f84>
    3
     
    Joel VanderWerf, Mar 7, 2005
    #7
  8. Excerpts from John Carter's mail of 6 Mar 2005 (EST):
    > The excellent article in callcc at
    > http://www.all-thing.net/Ruby/iterators_generators_and_continuations_in_ruby.html
    >
    > makes the following statement...
    >
    > The way to create a continuation is with Kernel#callcc. For what I
    > imagine are historical reasons, the continuation is passed as an
    > argument to a block, rather than returned directly. So the idiom to
    > get a continuation at the current point in the code is this:
    >
    > c = callcc { |c| c }
    >
    > Can anyone elaborate on this history?
    >
    > Or is there a deeper reason than mere history?


    The author of that article clearly didn't understand continuations as
    well as he thought! The block syntax does indeed serve a purpose: it
    becomes useful when you want to pass values around in continuation
    calls, as the ol'

    if @cont = callcc { |c| c }
    ## before
    end
    ## before + after

    trick doesn't work any more, if nil or false can be passed as values.
    See e.g. http://www.all-thing.net/Ruby/coroutines.html for a usage case.

    I've exchanged a few choice words with the author and he's updated the
    article to reflect this.

    --
    William <>
     
    William Morgan, Mar 9, 2005
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jim Bob

    Why does Ruby have callcc?

    Jim Bob, Aug 6, 2003, in forum: Ruby
    Replies:
    22
    Views:
    253
  2. zuzu
    Replies:
    14
    Views:
    251
    Phil Tomson
    Aug 23, 2004
  3. Mikael Brockman
    Replies:
    2
    Views:
    149
    Mikael Brockman
    Sep 25, 2004
  4. Bill Atkins

    callcc Semantics

    Bill Atkins, Oct 18, 2004, in forum: Ruby
    Replies:
    2
    Views:
    114
    Eric Hodel
    Oct 19, 2004
  5. Greg Fitzgerald

    Callcc problem in Generator

    Greg Fitzgerald, Jan 25, 2005, in forum: Ruby
    Replies:
    0
    Views:
    189
    Greg Fitzgerald
    Jan 25, 2005
Loading...

Share This Page