【问题标题】:Why does a Flip-Flop operator include the second condition?为什么触发器运算符包含第二个条件?
【发布时间】:2013-09-07 03:27:44
【问题描述】:

以下代码使用了触发器运算符。

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

为什么结果是3,4,5

我觉得应该是3,4

如教程中所述,此表达式在x == 3 时为真,并且在x == 5 之前一直为真。如果评估为假,如何打印“5”?谁能帮我澄清一下?

【问题讨论】:

标签: ruby flip-flop


【解决方案1】:

来自“The Ruby Programming Language”的重要链接是:

4.6.9.1 Boolean flip-flops

当 .. 和 ... 运算符用于条件语句时,例如 if 语句,或 在循环中,例如 while 循环(有关条件和循环的更多信息,请参见第 5 章), 他们不创建 Range 对象。相反,他们创建了一种特殊的布尔值 表达式称为触发器。触发器表达式的计算结果为真或假,就像 比较和等式表达式可以。关于一个非常不寻常的事情 然而,触发器表达式是它的值取决于先前评估的值 国家。这意味着触发器表达式具有与之关联的状态;它必须 记住有关先前评估的信息。因为它有状态,你会 期望触发器成为某种对象。但它不是——它是一个 Ruby 表达式,而且 Ruby 解释器将它需要的状态(只是一个布尔值)存储在表达式的内部解析表示中。

考虑到这一背景,考虑以下代码中的触发器。注意 代码中的第一个 .. 创建了一个 Range 对象。第二个创建触发器 表达式:

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

触发器由两个用 .. 运算符连接的布尔表达式组成,在 条件或循环的上下文。触发器表达式为假,除非且直到 左手表达式的计算结果为真。一旦这个表达成为真实,前- 压力“翻转”到持久的真实状态。它保持在那个状态,随后 评估返回真,直到右手表达式计算为真。当那个 发生这种情况时,触发器“翻转”回持续的错误状态。后续评估 表达式返回 false,直到左侧表达式再次变为 true。 在代码示例中,触发器被重复评估,x 的值从 1 到 10. 它从 false 状态开始,当 x 为 1 和 2 时评估为 false。 x==3,触发器翻转为真并返回真。当 x 为 4 和 5。但是,当 x==5 时,触发器会返回 false,并返回 false x 的剩余值。结果是这段代码打印了 345。

【讨论】:

    【解决方案2】:

    .. 或触发器是从 Perl 继承的,Perl 从 AWK 获得它并在 *nix 中使用 sed。它非常强大,但在您的特定用途中它相当晦涩,对于您想要的逻辑来说不是一个好的选择,尤其是在 Ruby 中。而是使用:

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

    哪些输出:

    3
    4
    5
    

    也就是说,当您需要从文件中提取一系列行时,它非常强大:

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

    哪些输出:

    Agatha
    Ahmed
    Ahmet
    

    Perl 允许使用仅使用当前读取行的行号(AKA $.)的更简洁的表达式,但 Ruby 不支持。

    还有使用正则表达式的选项,其行为与之前的比较类似:

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

    哪些输出:

    Wade
    Walt
    Walter
    Warren
    Wayne
    Wendell
    

    由于正则表达式有效,因此可以创建一个复杂的模式来根据匹配从文件中检索行。作为第一个,然后是第二个模式触发,线被捕获。如果稍后在文件中,另一行触发了第一个模式,则捕获将再次发生,直到第二个模式匹配。它非常强大:

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

    哪些输出:

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

    或者,对于我们会说晦涩代码的朋友:

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

    【讨论】:

      【解决方案3】:

      我找到了一段代码来说明触发器是如何工作的(就在这段代码出现的同一本书中,希望对像我一样有同样问题的人有所帮助)

      $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
      

      【讨论】:

        【解决方案4】:

        您在寻找独家系列吗?您可以使用三个点和cover? 方法。

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

        在您的示例中它打印 3,4,5 的原因是因为它说如果 x 在 3 到 5 的范围内则打印它。

        【讨论】:

          【解决方案5】:

          为了澄清@MurifoX 的评论,触发器在x==5 之前为真,因此特别是在x==5 时为真,但在此之后每次评估表达式时都是假的。因此,您仍然看到 5 正在打印。

          【讨论】:

            【解决方案6】:

            触发器表达式的计算结果为 true 或 false ,就像比较和相等表达式一样。 然而,触发器表达式的异常之处在于它的值取决于先前评估的值。这意味着触发器表达式具有与之关联的状态;它必须记住有关先前评估的信息。因为它有状态,你会 期望触发器成为某种对象。但它不是——它是一个 Ruby 表达式,而且 Ruby 解释器将它需要的状态(只是一个布尔值)存储在其内部已解析的表达式表示中。考虑到这一背景,请考虑以下代码中的触发器。请注意,代码中的第一个“..”创建了一个 Range 对象。第二个创建触发器表达式:

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

            触发器由两个用 .. 运算符连接的布尔表达式组成,在 条件或循环的上下文。触发器表达式为假,除非且直到 左手表达式的计算结果为 true 。一旦该表达式变为 true ,表达式“翻转”为持久的 true 状态。它保持在那个状态,随后 评估返回 true ,直到右侧表达式评估为 true 。当那个 发生这种情况时,触发器“翻转”回持续的错误状态。后续评估 表达式返回 false,直到左侧表达式再次变为 true。 在代码示例中,触发器被重复评估,x 的值从 1 到 10. 它以假状态开始,当 x 为 1 和 2 时评估为假。什么时候 x==3 ,触发器翻转为 true 并返回 true 。当 x 为 4 和 5 。但是,当 x==5 时,触发器会返回 false ,并返回 false x 的剩余值。结果是这段代码打印了 345 。

            【讨论】:

              猜你喜欢
              • 2018-10-14
              • 2020-10-28
              • 2012-04-25
              • 1970-01-01
              • 2012-09-22
              • 2012-03-28
              • 2016-02-03
              • 1970-01-01
              • 2020-09-10
              相关资源
              最近更新 更多