[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

FlipFlop Voodoo

Daniel Nugent

7/3/2005 4:45:00 AM

So I was reading through the retrospective on RedHanded today and saw
the piece of flipflops
(http://redhanded.hobix.com/inspect/hopscotchingArraysWithFlip...).

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}
a -> [nil, 12, nil, nil, nil, 16, 17, 18, nil, 20]

If there isn't a typo and I'm reading it right, then 18 should not be
in the output array since the second part of the flipflop should have
triggered the state machine to go back to the unset state. Now,
Pickaxe2 mentions that when the second condition evaluates to true on
the same call as the first condition, it will still output true
anyhow.

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.

If I'm missing something vital about this, I'd really appreciate
someone taking the time to explain it more thoroughly Because I
*think* I understand what's going on here, but my reading of Pickaxe2
would seem to indicate that I don't.
--
-Dan Nugent


5 Answers

Esteban Manchado Velázquez

7/3/2005 4:34:00 PM

0

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/hopscotchingArraysWithFlip...).
>
> 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 <zoso@foton.es> - http://ww...
EuropeSwPatentFree - http://EuropeSwPatentFree.his...


Daniel Nugent

7/3/2005 7:08:00 PM

0

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 <zoso@foton.es> 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/hopscotchingArraysWithFlip...).
> >
> > 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 <zoso@foton.es> - http://ww...
> EuropeSwPatentFree - http://EuropeSwPatentFree.his...
>
>


--
-Dan Nugent


Michael Campbell

7/3/2005 7:16:00 PM

0

On 7/3/05, Daniel Nugent <nugend@gmail.com> wrote:

> For one, there's no typo in my original message (I'm copying right out
> of Pickaxe2)

Not to be a pedant, but yes, there was. Here's your original:

> a = (11..20).collect {|i| (i%4 == 0)..(i%3 == 0) ? i ? nil}

The second "?" should be ":".


Hal E. Fulton

7/3/2005 8:03:00 PM

0

Michael Campbell wrote:
>
> Not to be a pedant

So, you've got something against pedants? ;)


Hal





Daniel Nugent

7/4/2005 5:44:00 AM

0

Whoops, you're right about that Michael, the carat being near the
second modulo operator confused me, didn't see the second question
mark at all.

Sorry. I maintain my points otherwise.

On 7/3/05, Hal Fulton <hal9000@hypermetrics.com> wrote:
> Michael Campbell wrote:
> >
> > Not to be a pedant
>
> So, you've got something against pedants? ;)
>
>
> Hal
>
>
>
>
>


--
-Dan Nugent