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

Reply via email to