Why does the Flip-Flop operator include the second condition?

The following code uses a trigger.

(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 the textbook, this expression becomes true when x == 3 and continues to be true until x == 5 . How could I print β€œ5” if it was erroneous? Can anyone clarify this for me?

+6
source share
6 answers

Important link starting with "Ruby Programming Language":

4.6.9.1 Boolean flip-flops

When the .. and ... operators are used in a conditional expression, such as an if statement, or in a loop, such as a while loop (for more on conventions and loops, see Chapter 5), they do not create Range objects. Instead, they create a special type of boolean expression called a trigger. The flip flop expression evaluates to true or false, as does comparison and equality. The unusually unusual thing about a flip-flop expression, however, is that its meaning depends on the meaning of previous evaluations, ations. This means that the expression of the flip flop is associated with it; this should remember the information about previous ratings. Since this is a condition, you would expect the flip flop to become some kind of object. But this is not his Ruby expression, but the Ruby interpreter stores the state (just one logical value) that is required in the internal parsed representation of the expression.

Given this background, consider the trigger in the following code. Notice that the first .. a Range object is created in the code. The second creates a trigger expression:

  (1..10).each {|x| print x if x==3..x==5 } 

A flip flop consists of two Boolean expressions associated with the .. operator in the context of a conditional or loop. A flip flop expression is false if, prior to, the lefthand expression is true. As soon as this expression has become true, pressing "turns" into a constant true state. It stays in this state, and then evaluations return true until the right expression evaluates to true. When this happens, the trigger "falls" back into a constant false state. Subsequent evaluations of the expression return false until the lefthand expression becomes true again. In the code example, the trigger is calculated repeatedly, for x values ​​from 1 to 10. It starts in a false state and evaluates to false when x is 1 and 2. When x == 3, the trigger switches to true and returns true. It continues to return true when x 4 and 5. If x == 5, the trigger returns to false and returns false for the remaining x values. As a result, this code prints 345.

+4
source

.. or a flip flop inherited from Perl, which received it from AWK and sed in * nix. It is very powerful, but in your specific use it is rather obscure and not a good choice for the logic you want, especially in Ruby. Use instead:

 (1..10).each {|x| puts x if (3..5) === x } 

What outputs:

 3 4 5 

However, this is extremely important when you need to extract a series of lines from a file:

 File.foreach('/usr/share/dict/propernames') { |li| puts li if ($. == 5 .. $. == 7) } 

What outputs:

 Agatha Ahmed Ahmet 

Perl allows you to use an even lowercase expression using only the line numbers of the current line (AKA $. ), But Ruby doesn't support this.

There is also the possibility of using regular expressions that behave similarly to the previous comparison:

 File.foreach('/usr/share/dict/propernames') { |li| puts li if (li[/^Wa/] .. li[/^We/]) } 

What outputs:

 Wade Walt Walter Warren Wayne Wendell 

Because the regex works, it's possible to create a complex pattern to extract strings from a file based on matches. As the first, then the second pattern, lines, is launched. If later in the file another line starts the first template, the capture will be performed again until the second template is found. This is wonderfully powerful:

 File.foreach('/usr/share/dict/propernames') { |li| puts li if ( li[/^Am/] .. li[/^An/] or li[/^Wa/] .. li[/^We/] ) } 

What outputs:

 Amanda Amarth Amedeo Ami Amigo Amir Amos Amy Anatole Wade Walt Walter Warren Wayne Wendell 

Or alternately, for our obscure codes of talking friends:

 File.foreach('/usr/share/dict/propernames') { |li| puts li if (li[/^(?:Am|Wa)/] .. li[/^(?:An|We)/]) } 
+3
source

I find a code snippet to illustrate how the trigger works (only in the same book where this code snippet appears, hope this helps those with the same question as me)

 $state = false # Global storage for flip-flop state def flipflop(x) # Test value of x against flip-flop if !$state # If saved state is false result = (x == 3) # Result is value of lefthand operand if result # If that result is true $state = !(x == 5) # Then saved state is not of the righthand operand end result # Return result else # Otherwise, if saved state is true $state = !(x == 5) # Then save the inverse of the righthand operand true # And return true without testing lefthand end end 
+1
source

Are you looking for an exclusive range? Can you use three dots and cover? method cover? .

 (1..10).each { |x| print "#{x}," if (3...5).cover?(x) } 

The reason it prints 3,4,5 in your example is because it says that if x is in the range of 3 to 5, print it.

0
source

To clarify @MurifoX's comment, the trigger is true to x==5 and thus true specifically when x==5 , but is false every time the expression evaluates after that. So you still see printed 5.

0
source

Flip flops express the value true or false, as do the expressions of comparison and equality. However, the unusually unusual thing about the expression of a flip flop is that its value depends on the value of previous estimates. This means that the expression of the flip flop is associated with it; he must remember the information about previous evaluations. Since this is a condition, you would expect the flip flop to become some kind of object. But this is not his Ruby expression, but the Ruby interpreter saves the state (just one logical value), which is required in the internal parsed representation of the expression. Based on this, consider the trigger in the following code. Note that the first ".." in the code creates a Range object. The second creates a trigger expression:

 (1..10).each {|x| print x if x==3..x==5 } 

A flip flop consists of two Boolean expressions associated with the .. operator in the context of a conditional or loop. A flip flop expression is false if, prior to, the lefthand expression is true. As soon as this expression has become true, the expression "turns" into a constant true state. It stays in this state, and then evaluations return true until the right expression evaluates to true. When this happens, the trigger "falls" back into a constant false state. Subsequent evaluations of the expression return false until the lefthand expression becomes true again. In the code example, the trigger is calculated repeatedly, for x values ​​from 1 to 10. It starts with a false state and evaluates to false when x is 1 and 2. when x == 3, the trigger switches to true and returns true. It continues to return true when x 4 and 5. However, with x == 5, the trigger returns to false and returns false for the remaining x values. As a result, this code prints 345.

0
source

Source: https://habr.com/ru/post/953082/


All Articles