From: Daniel Nugent Date: 2005-07-04T04:08:00+09:00 Subject: Re: FlipFlop Voodoo I think you're wrong here in that you've misunderstood what the purpose of the conditional range operator is. For one, there's no typo in my original message (I'm copying right out of Pickaxe2) Here's the first example they give: a = (11..20).collect {|i| (i%4 ==0)..(i%3 == 0) ? i : nil) a -> [nil, 12, nil, nil, nil, 16, 17, 18, nil, 20] Here, when i = 12, we can see that the first expression evaluates to true and the second expression evaluates to true. If the state machine moves each time one part of the expression evaluated to true, then it wouldn't print 12 since it would be back in the unset state (where it was before the first expression evaluated to true). The Pickaxe mentions this, that if they both evaluate on the same call it will finish in the unset state but the flipflop operator would still return true in that condition. However, when i = 16, it stays in the set state until i = 18, when the state machine should go back to the unset state and *not* return true if the Pickaxe is to be believed. a = (11..20).collect {|i| (i%4 ==0)...(i%3 == 0) ? i : nil) a -> [nil, 12, 13, 14, 15, 16, 17, 18, nil, 20] Here, when i = 12, the first expression evaluates to true, *but the second expression doesn't get a chance to*. Pickaxe2 states that the semantics of conditional ... causes a short circuit when the first expression evaluates to true. Thus, i%3 does not evaluate to 0 until i = 15. Once again, were the pickaxe to be believed, this should move the state machine into the unset state and the flipflop operator should not return true. If conditional ... worked as you expected, then 12-15 should be nil in the above example since ... would exclude 12 since it's the end of the range (1...1.to_a == [] for example) So, basically, I think I understand the semantics of it, just that there's a small error in Pickaxe2's explanation. It should say something like if expression2 is evaluated to true, the state machine is moved to the unset state after the operator has decided to return true. On 7/3/05, Esteban Manchado Vel�zquez wrote: > On Sun, Jul 03, 2005 at 01:44:32PM +0900, Daniel Nugent wrote: > > So I was reading through the retrospective on RedHanded today and saw > > the piece of flipflops > > (http://redhanded.hobix.com/inspect/hopscotchingArraysWithFlipFlops.html). > > > > Reading it I realized that I didn't quite understand how the > > flipfloperator worked exactly. So I grabbed the Pickaxe2 and read > > that it returns true when the state machine is in the set state at the > > end of the call. > > > > Looking at both why's examples, the ones in Pickaxe2, and through a > > little experimentation of my own and once again reviewing the state > > transition diagram in Pickaxe2, I figured there must be a typo. > > > > See example 1 on pg 342: > > > > a = (11..20).collect {|i| (i%4 == 0)..(i%3 == 0) ? i ? nil} > ^ > Typo here ------------------------------------------' > > Should be ":", of course. It's unrelated to what you're asking, anyway ;-) > > > a -> [nil, 12, nil, nil, nil, 16, 17, 18, nil, 20] > > [...] > > However, it does not explain why this happens or why it also outputs > > 18 even though 18%3==0 should evaluate to true and push the state > > machine into the unset state. > > The "problem" here is that two dot ranges _include_ the ending. What I > don't quite understand is this :-) > > --------------------------------- 8< --------------------------------- > zoso@velutha:~/tmp$ cat >number_list > one > two > three > four > five > zoso@velutha:~/tmp$ irb > irb(main):001:0> File.foreach('number_list') do |line| > irb(main):002:1* if line =~ /two/ .. line =~ /four/ > irb(main):003:2> puts "#{line.chomp} is included in the two..four range" > irb(main):004:2> end > irb(main):005:1> if line =~ /two/ ... line =~ /four/ > irb(main):006:2> puts "#{line.chomp} is included in the two...four > range" > irb(main):007:2> end > irb(main):008:1> end > two is included in the two..four range > two is included in the two...four range > three is included in the two..four range > three is included in the two...four range > four is included in the two..four range > four is included in the two...four range > => nil > irb(main):009:0> (1..20).to_a > => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] > irb(main):010:0> (1...20).to_a > => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] > --------------------------------- >8 --------------------------------- > > It seems that ranges in conditions always behave as "..", even if you use the > "..." operator. Another, simpler, example: > > --------------------------------- 8< --------------------------------- > irb(main):007:0> (1..20).each do |i| > irb(main):008:1* puts i if (i == 4 .. i == 5) > irb(main):009:1> end > 4 > 5 > => 1..20 > irb(main):010:0> (1..20).each do |i| > irb(main):011:1* puts i if (i == 4 ... i == 5) > irb(main):012:1> end > 4 > 5 > => 1..20 > --------------------------------- >8 --------------------------------- > > Is there any reason for this? Is it a bug? > > -- > Esteban Manchado Vel�zquez - http://www.foton.es > EuropeSwPatentFree - http://EuropeSwPatentFree.hispalinux.es > > -- -Dan Nugent