On 3/1/08, David Chelimsky <[EMAIL PROTECTED]> wrote: > On Sat, Mar 1, 2008 at 11:37 AM, Giles Bowkett <[EMAIL PROTECTED]> wrote: > > I appear to have written code which travels backwards through time: > > > > http://www.vimeo.com/742590 > > > > This disturbs me immensely. If anyone can explain it, that would be cool. > > > > I think it's an illusion brought about by how RSpec wraps the code it > > executes, and by the sheer weirdness of continuations. > > > This has absolutely nothing to do with RSpec. Do the same thing in > test/unit and you'll find the same result > (http://pastie.caboo.se/159803) > > Continuations ARE time machines. So when you called the continuation > again, it does in fact go back to where it exited the loop (from the > interrupt). > > Now I haven't looked to see why the second time "through time" it's > not working, but it actually makes perfect sense that it goes back in > time.
I can't read all of the code, but it appears that the up_to method in ContinuationLooper looks like this: 1: def up_to(interrupt) 2: accumulator = "" 3: continuation = nil 4: for i in 1..100 do 5: accumulator += "Value of i: #{i}<br/>\n" 6: callcc {|continuation| return accumulator, continuation} if i == interrupt 7: accumulator 8: end 9: end Ok now in the test we have: 10: it "resumes its continuation, returning a string" do 11: accumulator, continuation = ContinuationLooper.up_to(50) 12: continuation.class.should == Continuation 13: puts accumulator 14: puts continuation.call Now, when we first encounter line 11, we get to the point in the loop in the ContinuationLooper.up_to method where i == 50 and invoke callcc. This evaluates it's block argument which returns the accumulator and the continuation, returning them to line 12. So continuation here is a Continuation and the expectation is met. Now, we go on, and when we get to line 14, the continuation gets called, which puts us back at line 7 inside the loop, which continues until i gets to 100. The callcc doesn't get invoked again because i is now always > interrupt. Then the method returns the last expression in the loop which is simply: accumulator which is what gets returned as the value of the call in line 11 (i.e. the second time we've gotten there), and substituting the return value, the effect is as if line 11 were: accumulator, continuation = "Value of i: (1)<br/>\n...Value of i: (100)<br/>\n" Which because of the way Ruby parallel assignment works when there are not enough RHS values to go around sets the local continuation to nil. No mystery here at all. -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/ _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users