Thoughts o' the day: + Generators ("semi-coroutines") are wonderful tools and easy to implement without major changes to the PVM. Icon calls 'em generators, Sather calls 'em iterators, and they're exactly what you need to implement "for thing in object:" when object represents a collection that's tricky to materialize. Python needs something like that. OTOH, generators are pretty much limited to that. + Coroutines are more general but much harder to implement, because each coroutine needs its own stack (a generator only has one stack *frame*-- its own --to worry about), and C-calling-Python can get into the act. As Sam said, they're probably no easier to implement than call/cc (but trivial to implement given call/cc). + What may be most *natural* is to forget all that and think about a variation of Python threads implemented directly via the interpreter, without using OS threads. The PVM already knows how to handle thread-state swapping. Given Christian's stackless interpreter, and barring C->Python cases, I suspect Python can fake threads all by itself, in the sense of interleaving their executions within a single "real" (OS) thread. Given the global interpreter lock, Python effectively does only-one-at-a-time anyway. Threads are harder than generators or coroutines to learn, but A) Many more people know how to use them already. B) Generators and coroutines can be implemented using (real or fake) threads. C) Python has offered threads since the beginning. D) Threads offer a powerful mode of control transfer coroutines don't, namely "*anyone* else who can make progress now, feel encouraged to do so at my expense". E) For whatever reasons, in my experience people find threads much easier to learn than call/cc -- perhaps because threads are *obviously* useful upon first sight, while it takes a real Zen Experience before call/cc begins to make sense. F) Simulated threads could presumably produce much more informative error msgs (about deadlocks and such) than OS threads, so even people using real threads could find excellent debugging use for them. Sam doesn't want to use "real threads" because they're pigs; fake threads don't have to be. Perhaps x = y.SOME_ASYNC_CALL(r, s, t) could map to e.g. import config if config.USE_REAL_THREADS: import threading else: from simulated_threading import threading from config.shared import msg_queue class Y: def __init__(self, ...): self.ready = threading.Event() ... def SOME_ASYNC_CALL(self, r, s, t): result = [None] # mutable container to hold the result msg_queue.put((server_of_the_day, r, s, t, self.ready, result)) self.ready.wait() self.ready.clear() return result[0] where some other simulated thread polls the msg_queue and does ready.set() when it's done processing the msg enqueued by SOME_ASYNC_CALL. For this to scale nicely, it's probably necessary for the PVM to cooperate with the simulated_threading implementation (e.g., a simulated thread that blocks (like on self.ready.wait()) should be taken out of the collection of simulated threads the PVM may attempt to resume -- else in Sam's case the PVM would repeatedly attempt to wake up thousands of blocked threads, and things would slow to a crawl). Of course, simulated_threading could be built on top of call/cc or coroutines too. The point to making threads the core concept is keeping Guido's brain from exploding. Plus, as above, you can switch to "real threads" by changing an import statement. making-sure-the-global-lock-support-hair-stays-around-even-if-greg- renders-it-moot-for-real-threads<wink>-ly y'rs - tim
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4