Ruby中布尔值为0的内容是什么?

时间:2015-09-07 07:33:00

标签: ruby

在查看这些表达式的行为后:

1 and 0 #=> 0 
0 and 1 #=> 1

1 and true #=> true
0 and true #=> true
对我来说,无论逻辑表达式的评估结果如何,更像是ruby返回逻辑门的右侧值。我正在寻找它的原因。

2 个答案:

答案 0 :(得分:3)

您需要了解的两件事情:

  1. and(和&&)返回第一个操作数(如果为false),否则返回第二个操作数。
  2. falsenil以外的任何内容均为真,包括0

答案 1 :(得分:1)

TL; DR

Ruby表现得很好,但如果你来自另一种语言,可能会让人感到困惑。这种混淆最常由以下原因引起:

  1. 不了解Ruby中的真值和虚假值,尤其是在评估control expressions的真实性时。
  2. 使用and之类的流量控制运算符来测试相等而不是==
  3. 误解了解析器如何看待你的"比较"作为两个单独的表达。
  4. 要解决您描述的问题,请使用相等运算符来测试真实性。以下是更详细的解释。

    Ruby返回评估的最后一个表达式

    在Ruby中,每个表达式都返回一个值。当您评估表达式时:

    1 and 0 #=> 0 
    

    您没有像使用实际的布尔返回表达式那样检查每个表达式的真实性,例如:

    !!(1 and 0) #=> true
    

    相反,您只是按顺序评估两个表达式,除非第一个表达式的计算结果为 nil false 并将评估短路。无论哪种方式,Ruby都会返回最后一个表达式的值。在这种情况下,您可以使用以下结果获得相同的结果:

    1; 0 #=> 0
    

    Parser看到了什么

    使用Ruby标准库,您可以看到解析器看到的内容。例如:

    require 'pp'
    require 'ripper'
    
    pp Ripper.sexp '1 and 0'
    #=> [:program, [[:binary, [:@int, "1", [1, 0]], :and, [:@int, "0", [1, 6]]]]]
    

    使用ruby_parser gem代替Ripper时,S-expression可能更清晰,更易于阅读。例如:

    require 'pp'
    require 'ruby_parser'
    
    pp RubyParser.new.parse '1 and 0'
    #=> s(:and, s(:lit, 1), s(:lit, 0))
    

    无论哪种方式,由于第一个表达式1计算为整数文字(例如 nil false 以外的其他文字),0是然后评估。第二个Integer文本也计算为true,因此整个表达式为true(在此上下文中无关)并返回0,因为0是最后一个表达式。

    你真正想要的是什么

    在Ruby中,all values other than nil or false are true。您通常希望将表达式与诸如and之类的相等运算符进行比较,或者将表达式强制转换为具有!!的布尔上下文,而不是==运算符。例如:

    # Evaluate equality and return a Boolean result.
    1 == 1 #=> true
    0 == 1 #=> false
    
    # Evaluate whether an expression is equal to true. In this case,
    # the double-negation of `!!` casts each Integer as a Boolean value.
    !!1 == true #=> true
    !!0 == true #=> true
    
    # Use `and` flow-control operator to evaluate right-hand expression
    # if the left-hand side evaluates as truthy.
    (1) and (true)  #=> true
    (1) and (false) #=> false