[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

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

John Carter

3/6/2005 10:49:00 PM

7 Answers

Joel VanderWerf

3/6/2005 10:59:00 PM

0

John Carter wrote:
> The excellent article in callcc at
> http://www.all-thing.net/Ruby/iterators_generators_and_continuations_in...
>
>
> 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

3/6/2005 11:16:00 PM

0

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.


gabriele renzi

3/6/2005 11:25:00 PM

0

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.

Csaba Henk

3/7/2005 1:12:00 AM

0

On 2005-03-06, John Carter <john.carter@tait.co.nz> 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

Luke Graham

3/7/2005 1:14:00 AM

0

The block usually wants to return a useful value itself.


On Mon, 7 Mar 2005 08:16:17 +0900, Joel VanderWerf
<vjoel@path.berkeley.edu> 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


Joel VanderWerf

3/7/2005 1:55:00 AM

0

Luke Graham wrote:
> The block usually wants to return a useful value itself.
>
>
> On Mon, 7 Mar 2005 08:16:17 +0900, Joel VanderWerf
> <vjoel@path.berkeley.edu> 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


William Morgan

3/9/2005 1:38:00 AM

0

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...
>
> 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/corou... for a usage case.

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

--
William <wmorgan-ruby-talk@masanjin.net>