SitePoint Sponsor

User Tag List

Results 1 to 5 of 5
  1. #1
    SitePoint Zealot
    Join Date
    Aug 2005
    Posts
    139
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Ranges in Boolean Expressions

    Can someone explain how the state machine works for a range in a boolean expression? I'm trying to figure out WHY the block below would give a value for 17 rather than nil (and also, why wouldn't 15 pass the i%3 == 0 test?)

    Code:
    a = (11..20).collect {|i| (i%4 == 0)..(i%3 == 0) ? i : nil}  
    a   [nil, 12, nil, nil, nil, 16, 17, 18, nil, 20]


    And what is happening internally with the example below?

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

  2. #2
    SitePoint Zealot
    Join Date
    Aug 2005
    Posts
    139
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think I figured it out myself... If anyone cares to hear my explanation, I'd be glad to share it.

  3. #3
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I do!

  4. #4
    SitePoint Zealot
    Join Date
    Aug 2005
    Posts
    139
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This is how I *think* it works:

    Ruby maintains the true/false state of the boolean expression when using a range... it switches back and forth between the start and end value of the range with each state change. I think it's easiest to explain by stepping through the process using the example below:

    Code:
    a = (11..20).collect {|i| (i%4 == 0)...(i%3 == 0) ? i : nil}  
    a   [nil, 12, 13, 14, 15, 16, 17, 18, nil, 20]
    The initial state of the boolean expression is false.
    We start by passing the value 11 into the code block:

    11 is passed in, (11%4 == 0) is False, so the state does not change... it remains false, so nil is returned.
    12 is passed in, (12%4 == 0) is True, so the state CHANGES to true.. the value of 'i' is returned

    Since the state has now changed, ruby switches to the end value in our range when evaluating the boolean expression

    13 is passed in, now we use the end expression of the range: (i%3 == 0). Since (13%3 == 0) is False, no change is made to the state. However, Ruby remembers that the state was ALREADY true, so it STILL treats it as true, and returns the value of 'i'


    14 is passed in, (14%3 == 0) is false, so again, no state change. The boolean is still considered true, and the value of i is returned

    15 is passed in, (15%3 == 0) is True, so the state changes (since it was already true, it now changes to false). Ruby still returns the value of i before completing the loop. However, on the next iteration, it switches back to the first expression in the range - (i%4 == 0)

    16 is passed in, (16%4 == 0) is True also, so the state changes yet again (it was false, so now it's back to true!) the value of i is returned and again we switch to the end value of our range when evaluating the next iteration

    and so it goes... flipping back and forth between the start and end value of the range with each state change



    When you use the 2 dot range in a boolean expression, ruby will test the start and end value of the range during the SAME iteration IF the first expression of the range returns true... phew... so in effect it changes state twice in one iteration, while the 3 dot range I used above can only change state once with each iteration.


    Does that make sense? And is that how it really works??

  5. #5
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That does make sense, but I don't know if that's how it really works. Thanks for the explanation!


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •