Why does Ruby have callcc?

I understand, in a woozy sort of way, what callcc does. What I
don’t understand is what it’s really good for, and furthermore, what
it’s doing in Ruby.

It seems like all the explanations of callcc, in its various
implementations, stick to pretty simple examples, and almost always with
the proviso “you could more easily do this another way, but…”. The
exception might be with regard to Scheme, which, I guess, lacks a
catch/throw-like mechanism, so that callcc might be the best way to
escape from a deeply nested loop. Ruby, though, obviously has catch and
throw.

With some other languages, I wouldn’t think much of the inclusion of
such an apparently abstruse feature. But, from my reading of this list,
it seems like Matz is pretty conservative about adding features that
won’t get used, for whatever reason. I can only guess that he’d be twice
less likely to add features that don’t get used and are just plain
weird, as callcc seems to me even after having spent no short amount
of time trying to wrap my thick head around it.

So, how’d it get there? Is there some killer use for callcc that I’m
missing? Was it just for the “gee whiz” factor?

Jim Bob wrote:

So, how’d it get there? Is there some killer use for callcc that I’m
missing? Was it just for the “gee whiz” factor?

I’d be interested to read about some real-world examples where people have used callcc, not just to try it out, but because it was the “right” way to do something (for efficiency, or code brevity or whatever reason).

So, as opposed to the examples we find on some of the Ruby web pages, which are, as Bob said, effectively tutorials on how one might use callcc, can someone give us some examples of production code they’ve written that uses continuations?

Jim Bob invalid@invalid.com writes:

So, how’d it get there? Is there some killer use for callcc that I’m
missing? Was it just for the “gee whiz” factor?

I can’t explain the “how’d it get there” part; I’ll leave that to Matz
and friends.

Continuations are great for any situation in which you not only need
to jump out of a context (multiple nested loops, etc.), but also get
back in to the same context you left. You can’t do that with
catch/throw.

A good example of this is co-routines – you need to save your state
in the first function, start the second one, then jump back to where
you were in the first, and so on. This example runs two iterators
simultaneously:

Iterate simultaneously from a to b, and from b to a

def updown(a, b)
iter1, iter2 = ( a < b ? [a.method(:upto), b.method(:downto)] :
[a.method(:downto), b.method(:upto)] )
f, cc1, cc2 = nil

iter1.call(b) do |o|
callcc do |cc1|
f = o
cc2.call if(cc2)
iter2.call(a) do |i|
callcc do |cc2|
yield f, i
cc1.call if(cc1)
end
end
end
end
end

Of course, one can’t discount the considerable “Gee wiz” factor of
continuations ;-).

Dan

···


/^Dan Debertin$/ |
airboss@nodewarrior.org |
www.nodewarrior.org |

I think Seaside/Borges falls into this category.

I haven’t had a chance to use it in anger, but I think the idea is that
continuations can represent CGI session state; you code can be written in a
linear fashion (e.g. display page, fetch response, display next page, fetch
next response etc) without any explicit session maintenance. Furthermore, by
retaining continuation objects which represent earlier pages, it will work
even if the user clicks ‘back’ in their browser and re-enters data in a
previous form.

I’d have a number of concerns in a practical application - I’d want old
continuations to expire and be garbage-collected so that they don’t cause
infinite memory growth - but otherwise it sounds like a great way to write
web applications.

Regards,

Brian.

···

On Wed, Aug 06, 2003 at 08:38:25PM +0900, Harry Ohlsen wrote:

I’d be interested to read about some real-world examples where people have
used callcc, not just to try it out, but because it was the “right” way to
do something (for efficiency, or code brevity or whatever reason).

“Harry Ohlsen” harryo@qiqsolutions.com schrieb im Newsbeitrag
news:3F30E894.6010902@qiqsolutions.com

Jim Bob wrote:

So, how’d it get there? Is there some killer use for callcc that I’m
missing? Was it just for the “gee whiz” factor?

I’d be interested to read about some real-world examples where people
have used callcc, not just to try it out, but because it was the “right”
way to do something (for efficiency, or code brevity or whatever reason).

Standalone iterators. Jim Weirich posted some code here about 1 or 2
months ago. Maybe you’ll find it here: http://onestepback.org/

So, as opposed to the examples we find on some of the Ruby web pages,
which are, as Bob said, effectively tutorials on how one might use
callcc, can someone give us some examples of production code they’ve
written that uses continuations?

robert

Hi,

···

In message “Re: Why does Ruby have callcc?” on 03/08/06, Dan Debertin airboss@nodewarrior.org writes:

So, how’d it get there? Is there some killer use for callcc that I’m
missing? Was it just for the “gee whiz” factor?

I can’t explain the “how’d it get there” part; I’ll leave that to Matz
and friends.

The official answer is “why not”. I provide the features, you use
them.
matz.

I have been interested in these continuation-thingys for a while now, so now
that the subject came up, I decided to take a good look.

I now think I understand how they work, and when they might be used, but that
still leaves a few questions:

  1. Why do they have the strange syntax they have
  2. Why don’t they have more “meat” to them?

I found a bunch of websites all talking about continuations:

http://www.ai.mit.edu/~gregs/ll1-discuss-archive-html/threads.html#01372
http://www.ps.uni-sb.de/~duchier/python/continuations.html

The summary is that Continuations are essentially “goto with parameters”, or
even more simply, like setjmp, longjmp.

To do continuations, you need to save the state of the VM at the “site of the
continuation”, and then be able to load that up when asked to do so. Given
that, I am puzzled by the syntax they have in Ruby. First of all, why the
block? In most of the examples I’ve seen, there doesn’t seem to be a good
reason to have a block. The only reason the block is necessary seems to be
that the end of the block marks the location where Continuation#call will go
to. Also, why are they created by Kernel.callcc? Why not Continuation.new,
where the location from which to continue when the Continuation is called is
the next expression after .new.

The second issue is why Continuations have nothing but a .call method.
Because they should encapsulate things like stack and program-counter values
at the time of the call, it would seem to me like these are useful things to
have available.

Say, for instance, that Continuation had a “stack” accessor, it could return
something similar to Kernel.caller(). Continuation could also have a
"program_counter" attr_reader that would return some sort of binding object
(or a symbol or something) that would represent the location in the program
that would be jumped-to by .call. I think it would be interesting to be able
to manipulate Continuations in more ways than just .calling them. Maybe keep
an array of them around and jump to the one with the smallest stack? I don’t
know.

While I’m busy redesigning the language, what if Kernel.caller could return an
array of Continuation objects, any of which could be .called? If I
understand things correctly calling a continuation is essentially no
different from returning from a method call. The PC is set to a certain
address, the stack is unwound one level, and the only difference is that a
certain value is held somewhere (in a register?)

Anyhow, before today I really didn’t know anything about Continuations, so
maybe what I’m saying makes no sense at all, but I’d like to hear any
comments on the subject.

Ben

Brian Candler wrote:

I think Seaside/Borges falls into this category.

Do you have any URLs for this? I did a quick Google, but found a Smalltalk site. As far as I can tell, Seaside was some Ruby code that ended up in Smalltalk as Borges?

H.

Brian Candler wrote:

I’d be interested to read about some real-world examples where people have
used callcc, not just to try it out, but because it was the “right” way to
do something (for efficiency, or code brevity or whatever reason).

I think Seaside/Borges falls into this category.

I haven’t had a chance to use it in anger, but I think the idea is that
continuations can represent CGI session state; you code can be written in a
linear fashion (e.g. display page, fetch response, display next page, fetch
next response etc) without any explicit session maintenance. Furthermore, by
retaining continuation objects which represent earlier pages, it will work
even if the user clicks ‘back’ in their browser and re-enters data in a
previous form.

I’d have a number of concerns in a practical application - I’d want old
continuations to expire and be garbage-collected so that they don’t cause
infinite memory growth - but otherwise it sounds like a great way to write
web applications.

As I recall from RubyConf 2002, the use of continuations in Borges was
elegant but did not scale. Tracking all that previous state gets
expensive.

Perhaps see Avi Bryant’s presentation slides:

James

···

On Wed, Aug 06, 2003 at 08:38:25PM +0900, Harry Ohlsen wrote:

Regards,

Brian.

Heh, best quite ever.

···

On Wed August 6 2003 11:34 am, Yukihiro Matsumoto wrote:

I provide the features, you use them.

Brian Candler wrote:

I’d be interested to read about some real-world examples where people have
used callcc, not just to try it out, but because it was the “right” way to
do something (for efficiency, or code brevity or whatever reason).

I think Seaside/Borges falls into this category.

Yup, absolutely.

I haven’t had a chance to use it in anger, but I think the idea is that
continuations can represent CGI session state; you code can be written in a
linear fashion (e.g. display page, fetch response, display next page, fetch
next response etc) without any explicit session maintenance. Furthermore, by
retaining continuation objects which represent earlier pages, it will work
even if the user clicks ‘back’ in their browser and re-enters data in a
previous form.

That’s a pretty decent summary.

I’d have a number of concerns in a practical application - I’d want old
continuations to expire and be garbage-collected so that they don’t cause
infinite memory growth - but otherwise it sounds like a great way to write
web applications.

They certainly are expired and GC’ed. And you can control how many
continuations you keep around for a particular session. You can also
control how long sessions hang around - or you could swap them to disk
and keep them forever. Again, this is all speaking about the Smalltalk
version since I haven’t seent he Ruby code in quite some time and it may
well be true that you have less control of these things there.

If anyone’s interested in discussing Seaside or the benefits of
continuations further, the Seaside (Smalltalk people but others welcome)
community is all on the mailing list which you can sign up for at:

http://lists.squeakfoundation.org/listinfo/seaside

Cheers,

Julian

···

On Wed, Aug 06, 2003 at 08:38:25PM +0900, Harry Ohlsen wrote:

I have been interested in these continuation-thingys for a while now, so now
that the subject came up, I decided to take a good look.

I now think I understand how they work, and when they might be used, but that
still leaves a few questions:

  1. Why do they have the strange syntax they have

They don’t–there’s no inherent strange syntax to them. The syntax
comes from the language implementing the continuation semantics.

  1. Why don’t they have more “meat” to them?

Because there’s not much to them. Really, there isn’t. Continuations
(or, as I have recently been scolded about, first class
continuations) are pretty simple things.

I found a bunch of websites all talking about continuations:

http://www.ai.mit.edu/~gregs/ll1-discuss-archive-html/threads.html#01372
http://www.ps.uni-sb.de/~duchier/python/continuations.html

The summary is that Continuations are essentially “goto with parameters”, or
even more simply, like setjmp, longjmp.

Well… no. that’s not quite right. There’s rather more to
continuations than just that. Continuations are more a Location with
Environment and History. Closures are Locations with Environment, and
Functions are just Locations.

The second issue is why Continuations have nothing but a .call method.
Because they should encapsulate things like stack and program-counter values
at the time of the call, it would seem to me like these are useful things to
have available.

It’s generally considered Really Evil to look at anything inside a
continuation. Darned useful, though…

···

At 7:27 AM +0900 8/7/03, Ben Giddings wrote:

                                     Dan

--------------------------------------“it’s like this”-------------------
Dan Sugalski even samurai
dan@sidhe.org have teddy bears and even
teddy bears get drunk

First, I’m sure you know more about continuations than I do, because I
haven’t started to use them and only skimmed over discussions of them.

I found (as usual, I might add) that when trying to learn computer
programming concepts, there’s nothing quite like Scheme.*

Here’s a discussion that quickly leads to programming examples:

http://www.cs.utexas.edu/users/wilson/schintro/schintro_75.html#SEC82

And here’s another:

http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-
15.html#node_sec_13.1

And a final one:

http://www.scheme.com/tspl2d/further.html#g1835

I know that I, for one, would be appreciative if you came up with a
relatively straightforward way to explain callcc in Ruby.

Regards,

Mark

  • This does not detract from my enthusiasm for Ruby – studying Scheme
    helps me better understand Ruby, and computation in general.
···

On Wednesday, August 6, 2003, at 06:27 PM, Ben Giddings wrote:

[snip]
I found a bunch of websites all talking about continuations:

http://www.ai.mit.edu/~gregs/ll1-discuss-archive-html/
threads.html#01372
http://www.ps.uni-sb.de/~duchier/python/continuations.html

[snip]

Also, if you search for continuations on this page:

http://library.readscheme.org/

you’ll get a long list of academic research papers relating to
continuations in Scheme.

Regards,

Mark

···

On Wednesday, August 6, 2003, at 06:27 PM, Ben Giddings wrote:

[snip]

You are probably refering to the “Same Fringe” problem … you’ll find
it at http://jimweirich.umlcoop.net/articles/same_fringe/index.html

···

On Wed, 2003-08-06 at 10:42, Robert Klemme wrote:

Standalone iterators. Jim Weirich posted some code here about 1 or 2
months ago. Maybe you’ll find it here: http://onestepback.org/


– Jim Weirich jweirich@one.net http://onestepback.org

“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)

How consistent is this w/ your “no featuritis” policy? In LL2 you had
to explain why Ruby had callcc but no macros; your answer was that the
latter are more easily abused (“too powerful” IIRC).

Do you still believe that or does “I provide the features, you use them”
represent a new policy?

···

On Thu, Aug 07, 2003 at 12:34:31AM +0900, Yukihiro Matsumoto wrote:

Hi,

In message “Re: Why does Ruby have callcc?” > on 03/08/06, Dan Debertin airboss@nodewarrior.org writes:

So, how’d it get there? Is there some killer use for callcc that I’m
missing? Was it just for the “gee whiz” factor?

I can’t explain the “how’d it get there” part; I’ll leave that to Matz
and friends.

The official answer is “why not”. I provide the features, you use
them.


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Excusing bad programming is a shooting offence, no matter what the
circumstances.
– Linus Torvalds, to the linux-kernel list

It is.

I know of (and work with) about 5 or 6 companies doing ongoing
commercial development with Seaside. The gains we’ve seen over other
approaches to web development are huge. I’m a pragmatic guy; I’ve
built a lot of web frameworks, and discarded many of the ideas when
they didn’t work out. But I can confidently state that call/cc is a
strict requirement for any language I use for web development in the
future. There’s no going back.

I’d like to see the Borges project evolve so that the Ruby community
can really take advantage of this stuff - Eric’s done a nice job
adapting my throwaway proof of concept to be somewhat robust, but it’s
just the lowest layer of what we’ve been working with in Seaside.
Maybe I’ll find some time to write down the design in a form that
non-Smalltalkers can follow…

···

Brian Candler B.Candler@pobox.com wrote:

I think Seaside/Borges falls into this category.

I haven’t had a chance to use it in anger, but I think the idea is that
continuations can represent CGI session state; you code can be written in a
linear fashion (e.g. display page, fetch response, display next page, fetch
next response etc) without any explicit session maintenance. Furthermore, by
retaining continuation objects which represent earlier pages, it will work
even if the user clicks ‘back’ in their browser and re-enters data in a
previous form.

I’d have a number of concerns in a practical application - I’d want old
continuations to expire and be garbage-collected so that they don’t cause
infinite memory growth - but otherwise it sounds like a great way to write
web applications.

No, it was the other way round :slight_smile: Anyway,

http://raa.ruby-lang.org/list.rhtml?name=borges links to
http://segment7.net/ruby-code/borges/borges.html

which in turn links to information on Seaside. Also search for ‘seaside’ or
‘borges’ at http://ruby-talk.org/ as it’s been discussed before.

ISTR it uses Webrick, and since that’s now part of ruby-1.8.0, it should be
easier to install.

Cheers,

Brian.

···

On Wed, Aug 06, 2003 at 09:15:59PM +0900, Harry Ohlsen wrote:

Brian Candler wrote:

I think Seaside/Borges falls into this category.

Do you have any URLs for this? I did a quick Google, but found a
Smalltalk site. As far as I can tell, Seaside was some Ruby code that
ended up in Smalltalk as Borges?

james_b wrote:

Brian Candler wrote:

I’d be interested to read about some real-world examples where people
have
used callcc, not just to try it out, but because it was the “right”
way to
do something (for efficiency, or code brevity or whatever reason).

I think Seaside/Borges falls into this category.

I haven’t had a chance to use it in anger, but I think the idea is that
continuations can represent CGI session state; you code can be written
in a
linear fashion (e.g. display page, fetch response, display next page,
fetch
next response etc) without any explicit session maintenance.
Furthermore, by
retaining continuation objects which represent earlier pages, it will
work
even if the user clicks ‘back’ in their browser and re-enters data in a
previous form.

I’d have a number of concerns in a practical application - I’d want old
continuations to expire and be garbage-collected so that they don’t cause
infinite memory growth - but otherwise it sounds like a great way to
write
web applications.

As I recall from RubyConf 2002, the use of continuations in Borges was
elegant but did not scale. Tracking all that previous state gets
expensive.

Perhaps see Avi Bryant’s presentation slides:
Ruby | zenspider.com | by ryan davis

James

Well now, it’s not that it doesn’t scale - you just have to be careful
how you let it scale. There are several useful deployed applications
out there using Seaside. One in particular that Avi and I wrote has
been running for a year and a half with almost no maintenance on our
part. Now you’re right that you probably wouldn’t want to use it for a
site that received millions of hits in a day, but you have a quite a bit
of control over what state gets stored for backtracking and how many
previous page views you want to keep around for a session, etc. You can
definitely reasonably have a session kept under a couple of megs, which
could give you hundreds of concurrent users on a box with a Gig of ram.

Now I’m trying to remember the state of Borges (and the limitations of
the basic part he ported back to ruby for that talk) and I can’t
really… so it may be that what he demoed didn’t scale for some reason.
So it’s possible you’re remembering correctly :wink:

Julian

···

On Wed, Aug 06, 2003 at 08:38:25PM +0900, Harry Ohlsen wrote:

I have been interested in these continuation-thingys for a while now, so
now
that the subject came up, I decided to take a good look.

I now think I understand how they work, and when they might be used, but
that
still leaves a few questions:

  1. Why do they have the strange syntax they have

They don’t–there’s no inherent strange syntax to them. The syntax
comes from the language implementing the continuation semantics.

Well, be fair. He’s talking about continuations in Ruby
why do they look they way they do from a language user’s
perspective?

And I have to agree with him – it’s unintuitive to me why
there should be a block as opposed to just a “Continuation.new”
call. And likewise I don’t understand why callcc is in Kernel.

Hal

···

----- Original Message -----
From: “Dan Sugalski” dan@sidhe.org
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Wednesday, August 06, 2003 5:45 PM
Subject: Re: Why does Ruby have callcc?

At 7:27 AM +0900 8/7/03, Ben Giddings wrote:


Hal Fulton
hal9000@hypermetrics.com