I have ventured into learning some Ruby, for a number of reasons: - According to Pragmatic Programmers it's about time I learned another language - Rails, at least to see 1st-hand what the hype is all about ;) - XpNYC (which I recently started attending, RIP dpsg-NYC) is using Ruby
This is an especially important excercise for Python programmers considering that a number of PEPs (342, 343) coming down the pike are clearly influenced by some Ruby concepts.
Which brings me to another, very specific reason I wanted to to learn some Ruby - continuations. All the generator stuff could be viewed as a partial implementation of continuations, so I really wanted to see what the thing is like.
Continuations is obviously a pretty difficult concept, since there seems not to be a definitive explaination of it. It seems to take a lot of explainations to 'get' them, so I will add my own to the pile. (The example below, though not the entire explainaiton, assumes you 'get' Python's generators. If you don's, look it up - it's a good prep for continuations anyways).
To make best use of it I would start by learning the callcc Ruby syntax. Then try to work through the Generator example here (Ruby's equivalent of Python generators is implemented with continuations). Then meditate ;).
Here is my explaination that may help you work through the example. We've all seen some movie where a character could have done some small thing different with their life and have it determine their future in some drastic way (usually worse financially, but drastically better socially). Then a magical character (most commonly Bill Murray) shows up and teleports them into an alternative future, which makes them a better person, bla bla. Then they go back in time to the original choice and choose the other way. Ok.
Well, continuations are better than that. You ARE Bill Murray and the teleporting thingy is in YOUR hands. You can, at will, jump between your alternative futures and reap the benefits of both!
There is only one condition. You can only jump to predetermined points in your alternative futures. These points are quite similar to the 'save' points in a video game. So what you have to do is leave an initial 'save' point (point A), make a choice (choice A1) and go ahead a some in your current future. Then you are free to leave another 'save' point (point B) and teleport back to A. Once there, you choose something other than A1 and continue on with your life. Whenever you want, you can create another save point and go back to any of the preexisting saves - A of B so far. More than that, you can bring a "Gift" from your current future to any of the destination points. Imagine that, now our career-obssessed character can go on earning his millions, but he can at will teleport to his happy family-man self together with his wallet! Now that would be a rocking movie ;)
Ok, now that I am done with my fantasy, let me create a mind-map for the concepts. - You are the Control Flow of the program - 'Save points' are the results of callcc calls (they are only 'results' if you do callcc{|cont| return cont}, but that is a technicality) - the 'teleports' are the 'calls' to the continuation object, cont.call - the 'Gifts' are the optional parameters to cont.call
The main mental block that this explaination helped me with is understanding of what happends to the call stack (which makes a lot of us C programmers fall of the cliff with continuations, I think).
First, think of it as a call chain rather than stack (stack is a particular data structure implementing a call chain that is not compatible with continuations).
Then remember that the call chain is alive and well, it's just that you have two or more of them with continuaitons. If you 'continue' into a function that returs a value, that is exactly what will happen - it will return the value. But, you ask me, how can I return the value from that function when I still need to return from cont.call? I can't return to two places! Simple: cont.call() is not a usual function call. It's a 'teleport'. It never returns. You, Mr ControlFlow, can choose to jump back a nearby point that you jumped from, but that is your choice. You don't have to return, cont.call won't make you.
I know this won't be enough, but it may help someone 'click', which will make me happy.