Ben Giddings wrote:
def foo(cc, a, b)
puts a
cc.call b
end
puts Continuation.run(method(:foo), 1, 2)
Which prints
1
2
Wouldn’t it print 1 and return 2?
Well, I did “puts Continuation.run(method(:foo), 1, 2)”, which prints
the 2 that it returns
Anyhow, I think that’s a worthwhile addition to the class. The only
thing that concerns me a bit about that way of doing things is that
it’s not completely clear that “foo” is a function that has to accept
a continuation as its first argument. You really want to not only
check to see if the object responds to “call” but to see if it is a
subtype of function that accepts a continuation as its first
argument. This makes me think of Java threading stuff, where you
commonly test to see if something implements the runnable interface.
Maybe a better idea might be a class like ContinuationConsumer(?) that
stores the continuation as a member variable:
class ContinuationConsumer
attr_accessor :cc
def call(first, second)
…
@cc.call( … )
end
end
def Continuation.run(*args)
callcc do |cc|
if block_given?
yield cc
else
func_or_obj, *rest = args
if func_or_obj.respond_to? :call
if func_or_obj.kind_of? ContinuationConsumer
func_or_obj.cc = cc
func_or_obj.call(*rest)
else
func_or_obj.call(cc, *rest)
end
end
end
end
end
I’m too tired to think this through properly right now, so I’m just
tossing it out there as is. This isn’t the duck-typing-ist way of
doing things, so any suggestions to make it cleaner or just overall
better would be welcome.
Well, you could do that, but as you said, it’s not exactly duck typing.
Presumably if someone’s
passing a function to callcc, it will expect a continuation as its first
argument, otherwise it wouldn’t
make sense to pass the function in the first place, so I wouldn’t worry
about callcc figuring out
if the function intends to use the arguments correctly (besides, you
don’t do that for all other
functions you call).
I like Java, but making “first-class functions” in it has always
bothered me. It essentially requires
creating a separate class/interface for each return type (each primitive
type and Object), which
is messy. Also, Runnable is only really around because 1 - Java is
statically typed and 2- the
thread needs to make sure that the object has a run() method. Runnable
is an efficient way
to do this in Java, but in Ruby it’s easy to use respond_to? for the
same purpose. Theoretically,
in Java you could use reflection to find out if an object has a run
method and call that method
without having the object implement the Runnable interface, but that’d
be slow and complex.
Ruby is much nicer in this regard.
And like you, I’m not sure that I like Continuation.run as a name for
it, although I can’t come up with a good name either. I’d say
Continuation.call, but I think that’d be too corn-fusing.
Yeah, call is really what I keep wanting to name it, but I can’t
imagine it not being confusing. Maybe Continuation.use?
I don’t think use, or even call is the right thing to call it.
Continuation.call_with_current would
be more accurate, if verbose. Or perhaps Continuation.pass_current_to.
The thing that bothers
me about any of these is that it doesn’t accurately portray what’s going
on. It would read better
if you could do something like:
fun(Continuation.current, arg1, arg2, …)
But there again that’s less generall than callcc, because it doesn’t let
you do anything like:
callcc { |cc|
# do stuff …
fun(cc, arg1, arg2, …)
}
That’s why call-with-current-continuation and callcc work the way they
do. They do what
they say they do and no more, but are general enough to do all the more
specific stuff.
I don’t know that either of us will be able to come up with a method
name that expresses
what’s going on well in Object.verb form.
The best I can come up with is Continuation.call_with_current_continuation
Or maybe:
Continuation.call_method_or_block_with_current_continuation_and_maybe_pass_some_arguments_too

It’s past my bed time.
···
On Thursday, August 7, 2003, at 11:32 PM, Dan Doel wrote: