FlipFlop Voodoo

Discussion in 'Ruby' started by Daniel Nugent, Jul 3, 2005.

  1. 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 =3D (11..20).collect {|i| (i%4 =3D=3D 0)..(i%3 =3D=3D 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=3D=3D0 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.
    --=20
    -Dan Nugent
     
    Daniel Nugent, Jul 3, 2005
    #1
    1. Advertisements

  2. ^
    Typo here ------------------------------------------'

    Should be ":", of course. It's unrelated to what you're asking, anyway=
    ;-)
    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 =3D~ /two/ .. line =3D~ /four/
    irb(main):003:2> puts "#{line.chomp} is included in the two..four r=
    ange"
    irb(main):004:2> end
    irb(main):005:1> if line =3D~ /two/ ... line =3D~ /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
    =3D> nil
    irb(main):009:0> (1..20).to_a
    =3D> [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
    =3D> [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 =3D=3D 4 .. i =3D=3D 5)
    irb(main):009:1> end
    4
    5
    =3D> 1..20
    irb(main):010:0> (1..20).each do |i|
    irb(main):011:1* puts i if (i =3D=3D 4 ... i =3D=3D 5)
    irb(main):012:1> end
    4
    5
    =3D> 1..20
    --------------------------------- >8 ---------------------------------

    Is there any reason for this? Is it a bug?

    --=20
    Esteban Manchado Vel=E1zquez <> - http://www.foton.es
    EuropeSwPatentFree - http://EuropeSwPatentFree.hispalinux.es
     
    Esteban Manchado Velázquez, Jul 3, 2005
    #2
    1. Advertisements

  3. 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 =3D (11..20).collect {|i| (i%4 =3D=3D0)..(i%3 =3D=3D 0) ? i : nil)
    a -> [nil, 12, nil, nil, nil, 16, 17, 18, nil, 20]

    Here, when i =3D 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 =3D 16, it stays in the
    set state until i =3D 18, when the state machine should go back to the
    unset state and *not* return true if the Pickaxe is to be believed.

    a =3D (11..20).collect {|i| (i%4 =3D=3D0)...(i%3 =3D=3D 0) ? i : nil)
    a -> [nil, 12, 13, 14, 15, 16, 17, 18, nil, 20]

    Here, when i =3D 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 =3D 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 =3D=3D [] 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.


    --=20
    -Dan Nugent
     
    Daniel Nugent, Jul 3, 2005
    #3
  4. Not to be a pedant, but yes, there was. Here's your original:
    The second "?" should be ":".
     
    Michael Campbell, Jul 3, 2005
    #4
  5. Daniel Nugent

    Hal Fulton Guest

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


    Hal
     
    Hal Fulton, Jul 3, 2005
    #5
  6. 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.


    --=20
    -Dan Nugent
     
    Daniel Nugent, Jul 4, 2005
    #6
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.