From: Colin Bartlett Date: 2009-10-09T00:21:30+09:00 Subject: Re: On Ranges as conditions On Wed, Oct 7, 2009 at 1:08 PM, Ken Bloom wrote: > Pretty cool! Thanks for pointing this syntax out! I don't recall seeing > it in Pickaxe. It's definitely in the first (2001) edition as "Ranges as conditions": _A range used in a boolean expression acts as a flip-flop. _ It has two states, set and unset, and is initially unset. _ On each call, the range cycles through the state machine ... _ The range returns true if it is in the set state at the end of the call, _ and false otherwise. _The two-dot form of a range behaves slightly differently than the three-dot form. _ When the two-dot form first makes the transition from unset to set, _it immediately evaluates the end condition and makes the transition accordingly. _This means that if expr1 and expr2 both evaluate to true on the same call, _the two-dot form will finish the call in the unset state. _However, it still returns true for this call. . *But* - as Rick DeNatale and Markus Roberts posted - in these expressions the ".." and "..." don't create ranges but create "flip-flop" expressions, so I think it's misleading to call these "ranges", and I think the explanations in "The Ruby Programming Language" are better because they make that clear. > > One question: > > irb(main):013:0> a=%w{foo start bar end baz start foo bar end baz} > => ["foo", "start", "bar", "end", "baz", "start", "foo", "bar", "end", > "baz"] > irb(main):014:0> a.each {|i| puts i + (if i =~ /start/ .. i =~ /end/ then > " triggered" else "" end) } > foo > start triggered > bar triggered > end triggered > baz > start triggered > foo triggered > bar triggered > end triggered > baz > => ["foo", "start", "bar", "end", "baz", "start", "foo", "bar", "end", > "baz"] > irb(main):015:0> a.each {|i| puts i + (if i =~ /start/ ... i =~ /end/ > then " triggered" else "" end) } > foo > start triggered > bar triggered > end triggered > baz > start triggered > foo triggered > bar triggered > end triggered > baz > > Shouldn't the last version (using ... instead of ..) logically omit the > end line from the triggered section? > If I understand your question correctly, according to "Programming Ruby" and "The Ruby Programming Language" the ".." and "..." refer to *when* the flip-flop expressions are or are not evaluated, as the quote above from Pickaxe ("Programming Ruby") says. Does the following (irb) code explain this? An = [1, 2, 3, 5, 2.0, 3.0, 5.0] #=> [1, 2, 3, 5, 2.0, 3.0, 5.0] def ffn(b, e, dots = "..") aa = [] ffop = "x==#{b} #{dots} x>=#{e}" expr = "An.each { |x| aa << x if #{ffop} }" puts "expr #=> " + expr eval expr aa end #=> nil ffn 2, 3, ".." # expr #=> An.each { |x| aa << x if x==2 .. x>=3 } #=> [2, 3, 2.0, 3.0] ffn 2, 3, "..." # expr #=> An.each { |x| aa << x if x==2 ... x>=3 } #=> [2, 3, 2.0, 3.0] fn 2, 2, ".." # expr #=> An.each { |x| aa << x if x==2 .. x>=2 } #=> [2, 2.0] ffn 2, 2, "..." # expr #=> An.each { |x| aa << x if x==2 ... x>=2 } #=> [2, 3, 2.0, 3.0]