Ben Giddings wrote: > On Thursday, August 7, 2003, at 11:32 PM, Dan Doel 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. - Dan