简体   繁体   English

为什么触发器操作符包含第二个条件?

[英]Why does a Flip-Flop operator include the second condition?

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 ? 为什么结果3,4,5

I think it should be 3,4 . 我认为它应该是3,4

As mentioned in a tutorial, this expression becomes true when x == 3 , and continues to be true until x == 5 . 正如教程中所提到的,当x == 3时,该表达式变为true,并且在x == 5之前一直为真。 How could '5' been printed if it evaluates to false? 如果评价为假,怎么会打印'5'? Could anyone please clarify that for me? 有人可以请我澄清一下吗?

The important link, from "The Ruby Programming Language" is : “Ruby编程语言”的重要环节是:

4.6.9.1 Boolean flip-flops

When the .. and ... operators are used in a conditional, such as an if statement, or in a loop, such as a while loop (see Chapter 5 for more about conditionals and loops), they do not create Range objects. 当..和...运算符用于条件(如if语句)或循环(例如while循环)时(有关条件和循环的更多信息,请参阅第5章),它们不会创建Range对象。 Instead, they create a special kind of Boolean expression called a flip-flop. 相反,他们创建了一种特殊的布尔表达式,称为触发器。 A flip-flop expression evaluates to true or false, just as comparison and equality expressions do. 触发器表达式的计算结果为true或false,就像比较和等式表达式一样。 The extraordinarily unusual thing about a flip-flop expression, however, is that its value depends on the value of previous evalu- ations. 然而,关于触发器表达的非常不寻常的事情是它的值取决于先前评估的值。 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. 但它不是 - 它是一个Ruby表达式,并且Ruby解释器在其表达式的内部解析表示中存储它所需的状态(只是一个布尔值)。

With that background in mind, consider the flip-flop in the following code. 考虑到这一背景,请考虑以下代码中的触发器。 Note that the first .. in the code creates a Range object. 请注意,代码中的第一个..创建一个Range对象。 The second one creates the flip-flop expression: 第二个创建触发器表达式:

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

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. 触发器表达式为false,除非并且直到左手表达式的计算结果为真。 Once that expression has become true, the ex- pression “flips” into a persistent true state. 一旦表达式成为现实,表达式就会“翻转”为持久的真实状态。 It remains in that state, and subsequent evaluations return true until the righthand expression evaluates to true. 它保持在该状态,随后的评估将返回true,直到右侧表达式求值为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. 对表达式的后续计算返回false,直到左手表达式再次变为true。 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. 在代码示例中,触发器被重复计算,x的值从1到10.它从假状态开始,当x是1和2时评估为假。当x == 3时,翻转 - 翻转翻转为true并返回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. 当x为4和5时,它继续返回true。然而,当x == 5时,触发器将翻转为false,并对x的剩余值返回false。 The result is that this code prints 345. 结果是此代码打印345。

.. or flip-flop is inherited from Perl which got it from AWK and sed in *nix. ..或者触发器继承自Perl,它从AWK获得并在* 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. 它功能非常强大,但在你的特定用途中它是相当模糊的,并不是你想要的逻辑的好选择,特别是在Ruby中。 Instead use: 而是使用:

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

Which outputs: 哪个输出:

3
4
5

That said, it's extremely powerful when you need to extract a range of lines from a file: 也就是说,当您需要从文件中提取一系列行时,它非常强大:

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

Which outputs: 哪个输出:

Agatha
Ahmed
Ahmet

Perl allows an even more-terse expression using only the line numbers of the currently read line (AKA $. ) but Ruby doesn't support that. Perl只使用当前读取行(AKA $. )的行号允许更简洁的表达式,但Ruby不支持它。

There's also the option of using regular expressions, which behave similarly as the previous comparison: 还可以选择使用正则表达式,其行为与之前的比较相似:

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

Which outputs: 哪个输出:

Wade
Walt
Walter
Warren
Wayne
Wendell

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: 它非常强大:

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

Which outputs: 哪个输出:

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

Or alternately, for our obscure-code speaking friends: 或者,对于我们模糊代码的朋友说:

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

I find a piece of code to illustrate how the flip-flop works (just in the same book where this piece of code appears, hope it helps for those having same question like 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

Are you looking for an exclusive range? 您在寻找专属系列吗? You can use three dots and the cover? 你可以使用三个点和cover? method. 方法。

(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 if x is in the range from 3 to 5 print it. 在你的例子中它打印3,4,5的原因是因为它表示如果x在3到5的范围内打印它。

To clarify the comment by @MurifoX, The flip-flop is true until x==5 , and thus true specifically when x==5 , but is false every time the expression is evaluated after that. 为了澄清@MurifoX的注释,触发器在x==5之前是真的,因此当x==5时是真的,但是每次在此之后计算表达式时它都是假的。 Thus you are still seeing 5 being printed. 因此,你仍然看到5被打印。

A flip-flop expression evaluates to true or false , just as comparison and equality expressions do. 触发器表达式的计算结果为true或false,就像比较和等式表达式一样。 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. 但它不是 - 它是一个Ruby表达式,并且Ruby解释器在其表达式的内部解析表示中存储它所需的状态(只是一个布尔值)。 With that background in mind, consider the flip-flop in the following code. 考虑到这一背景,请考虑以下代码中的触发器。 Note that the first ".." in the code creates a Range object. 请注意,代码中的第一个“..”创建一个Range对象。 The second one creates the flip-flop expression: 第二个创建触发器表达式:

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

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 . 触发器表达式为false,除非并且直到左手表达式的计算结果为真。 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 . 它保持在该状态,随后的评估将返回true,直到右侧表达式求值为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. 对表达式的后续计算返回false,直到左手表达式再次变为true。 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 . 在代码示例中,触发器被重复评估,x的值从1到10.它以假状态开始,并且当x是1和2时评估为假。 When x==3 , the flip-flop flips to true and returns true . 当x == 3时,触发器翻转为真并返回true。 It continues to return true when x is 4 and 5 . 当x为4和5时,它继续返回true。 When x==5 , however, the flip-flop flops back to false , and returns false for the remaining values of x . 然而,当x == 5时,触发器将翻转为假,并对x的剩余值返回false。 The result is that this code prints 345 . 结果是此代码打印345。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM