The following code is using a flip-flop operator.
(1..10).each {|x| print "#{x}," if x==3..x==5 }
Why are the results 3,4,5
?
I think it should be 3,4
.
As mentioned in a tutorial, this expression becomes true when x == 3
, and continues to be true until x == 5
. How could '5' been printed if it evaluates to false? Could anyone please clarify that for me?
Are you looking for an exclusive range? You can use three dots and the
cover?
method.The reason it prints 3,4,5, in your example is because it says if x is in the range from 3 to 5 print it.
The important link, from "The Ruby Programming Language" is :
4.6.9.1 Boolean flip-flops
..
or flip-flop is inherited from Perl which got it from AWK and sed in *nix. It's very powerful, but in your particular use it's fairly obscure and not a good choice for the logic you want, especially in Ruby. Instead use:Which outputs:
That said, it's extremely powerful when you need to extract a range of lines from a file:
Which outputs:
Perl allows an even more-terse expression using only the line numbers of the currently read line (AKA
$.
) but Ruby doesn't support that.There's also the option of using regular expressions, which behave similarly as the previous comparison:
Which outputs:
Because regex work, it's possible to create a complex pattern to retrieve lines from a file based on matches. As the first, then the second pattern trigger, lines are captured. If, later in the file, another line triggers the first pattern, capturing will again occur until the second pattern matches. It's wonderfully powerful:
Which outputs:
Or alternately, for our obscure-code speaking friends:
To clarify the comment by @MurifoX, The flip-flop is true until
x==5
, and thus true specifically whenx==5
, but is false every time the expression is evaluated after that. Thus you are still seeing 5 being printed.A flip-flop expression evaluates to true or false , just as comparison and equality expressions do. The extraordinarily unusual thing about a flip-flop expression, however, is that its value depends on the value of previous evaluations. This means that a flip-flop expression has state associated with it; it must remember information about previous evaluations. Because it has state, you would expect a flip-flop to be an object of some sort. But it isn’t—it’s a Ruby expression, and the Ruby interpreter stores the state (just a single Boolean value) it requires in its internal parsed representation of the expression. With that background in mind, consider the flip-flop in the following code. Note that the first ".." in the code creates a Range object. The second one creates the flip-flop expression:
The flip-flop consists of two Boolean expressions joined with the .. operator, in the context of a conditional or loop. A flip-flop expression is false unless and until the lefthand expression evaluates to true . Once that expression has become true , the expression “flips” into a persistent true state. It remains in that state, and subsequent evaluations return true until the righthand expression evaluates to true . When that happens, the flip-flop “flops” back to a persistent false state. Subsequent evaluations of the expression return false until the lefthand expression becomes true again. In the code example, the flip-flop is evaluated repeatedly, for values of x from 1 to 10. It starts off in the false state, and evaluates to false when x is 1 and 2 . When x==3 , the flip-flop flips to true and returns true . It continues to return true when x is 4 and 5 . When x==5 , however, the flip-flop flops back to false , and returns false for the remaining values of x . The result is that this code prints 345 .