
[Sam]
Continuations are more powerful than coroutines, though I admit they're a bit esoteric.
"More powerful" is a tedious argument you should always avoid <wink>.
I programmed in Scheme for years without seeing the need for them. But when you need 'em, you *really* need 'em. No way around it.
For my purposes (massively scalable single-process servers and clients) threads don't cut it... for example I have a mailing-list exploder that juggles up to 2048 simultaneous SMTP connections. I think it can go higher - I've tested select() on FreeBSD with 16,000 file descriptors.
The other point being that you want to avoid "inside out" logic, though, right? Earlier you posted a kind of ideal: Recently I've written an async server that needed to talk to several other RPC servers, and a mysql server. Pseudo-example, with possibly-async calls in UPPERCASE: auth, archive = db.FETCH_USER_INFO (user) if verify_login(user,auth): rpc_server = self.archive_servers[archive] group_info = rpc_server.FETCH_GROUP_INFO (group) if valid (group_info): return rpc_server.FETCH_MESSAGE (message_number) else: ... else: ... I assume you want to capture a continuation object in the UPPERCASE methods, store it away somewhere, run off to your select/poll/whatever loop, and have it invoke the stored continuation objects as the data they're waiting for arrives. If so, that's got to be the nicest use for continuations I've seen! All invisible to the end user. I don't know how to fake it pleasantly without threads, either, and understand that threads aren't appropriate for resource reasons. So I don't have a nice alternative.
... | >>> import callcc | >>> saved = None | >>> def thing(n): | ... if n == 2: | ... global saved | ... saved = callcc.new() | ... print 'n==',n | ... if n == 0: | ... print 'Done!' | ... else: | ... thing (n-1) | ... | >>> thing (5) | n== 5 | n== 4 | n== 3 | n== 2 | n== 1 | n== 0 | Done! | >>> saved | <Continuation object at 80d30d0> | >>> saved.throw (0) | n== 2 | n== 1 | n== 0 | Done! | >>> saved.throw (0) | n== 2 | n== 1 | n== 0 | Done! | >>>
Suppose the driver were in a script instead: thing(5) # line 1 print repr(saved) # line 2 saved.throw(0) # line 3 saved.throw(0) # line 4 Then the continuation would (eventually) "return to" the "print repr(saved)" and we'd get an infinite output tail of: Continuation object at 80d30d0> n== 2 n== 1 n== 0 Done! Continuation object at 80d30d0> n== 2 n== 1 n== 0 Done! Continuation object at 80d30d0> n== 2 n== 1 n== 0 Done! Continuation object at 80d30d0> n== 2 n== 1 n== 0 Done! ... and never reach line 4. Right? That's the part that Guido hates <wink>. takes-one-to-know-one-ly y'rs - tim