需要澄清Ruby逻辑运算符

时间:2022-11-27 17:09:31

Recently I started learning Ruby. I am practicing logical operators in irb and I got these results, which I don't understand. Can you please clarify these examples for me?

最近我开始学习Ruby。我正在irb中练习逻辑运算符,我得到了这些结果,我不明白。你能给我解释一下这些例子吗?

1 and 0
#=> 0 

0 and 1
#=> 1 

0 && 1
#=> 1 

3 个解决方案

#1


6  

As opposed to other languages like C, in Ruby all values except for nil and false are considered “truthy”. This means, that all these values behave like true in the context of a boolean expression.

与其他语言如C不同,在Ruby中除了nil和false之外的所有值都被认为是“真实的”。这意味着,所有这些值在布尔表达式的上下文中都表现为true。

Ruby's boolean operators will not return true or false. Instead, they return the first operand that causes the evaluation of the condition to be complete (also known as short-circuit evaluation). For boolean and that means, it will either return the first “falsy” operand or the last one:

Ruby的布尔运算符不会返回真或假。相反,它们返回第一个操作数,从而导致对条件的评估完成(也称为短路评估)。对于布尔值,它要么返回第一个“falsy”操作数,要么返回最后一个:

false && 1    # => false     (falsy)
nil   && 1    # => nil       (falsy)
false && nil  # => false     (falsy)
1     && 2    # => 2         (truthy)

For boolean or that means, it will either return the first “truthy” operand or the last one:

对于布尔值,它要么返回第一个“truthy”操作数,要么返回最后一个:

false || 1    # => 1         (truthy)
nil   || 1    # => 1         (truthy)
false || nil  # => nil       (falsy)
1     || 2    # => 1         (truthy)

This allows for some interesting constructs. It is a very common pattern to use || to set default values, for example:

这允许一些有趣的结构。使用||设置默认值是一种非常常见的模式,例如:

def hello(name)
  name = name || 'generic humanoid'
  puts "Hello, #{name}!"
end

hello(nil)    # Hello, generic humanoid!
hello('Bob')  # Hello, Bob!

Another similar way to acheive the same thing is

另一种类似的方法是。

name || (name = 'generic humanoid')

With the added benefit that if name is truthy, no assignment is performed at all. There is even a shortcut for this assignment of default values:

附加的好处是,如果名称是真实的,则根本不执行任何赋值。甚至还有一个分配默认值的快捷方式:

name ||= 'generic humanoid'

If you paid careful attention you will have noticed that this may cause some trouble, if one valid value is false:

如果你仔细注意,你会发现这可能会引起一些麻烦,如果一个有效值是假的:

destroy_humans = nil
destroy_humans ||= true
destroy_humans
#=> true

destroy_humans = false
destroy_humans ||= true
destroy_humans
#=> true, OMG run!

This is rarely the desired effect. So if you know that the values can only be a String or nil, using || and ||= is fine. If the variable can be false, you have to be more verbose:

这很少是期望的效果。如果你知道值只能是一个字符串或nil,使用||和||=就可以了。如果变量可以为false,则必须更详细:

destroy_humans = nil
destroy_humans = true if destroy_humans.nil?
destroy_humans
#=> true

destroy_humans = false
destroy_humans = true if destroy_humans.nil?
destroy_humans
#=> false, extinction of humanity digressed!

That was close! But wait, there is another caveat – specifically with the usage of and and or. These should never be used for boolean expressions, because they have very low operator precedence. That means they will be evaluated last. Consider the following examples:

这是近了!但是,等等,还有另外一个警告——特别是关于and和or的用法。这些不应该用于布尔表达式,因为它们的运算符优先级很低。这意味着它们将在最后进行评估。考虑下面的例子:

is_human = true
is_zombie = false
destroy_human = is_human && is_zombie
destroy_human
#=> false

is_human = true
is_zombie = false
destroy_human = is_human and is_zombie
destroy_human
#=> true, Waaaah but I'm not a zombie!

Let me add some parentheses to clarify what's happening here:

让我加一些括号来说明这里发生了什么

destroy_human = is_human && is_zombie
# equivalent to
destroy_human = (is_human && is_zombie)

destroy_human = is_human and is_zombie
# equivalent to
(destroy_human = is_human) and is_zombie

So and and or are really just useful as “control-flow operators”, for example:

因此,或者实际上只是作为“控制流操作符”有用,例如:

join_roboparty or fail 'forever alone :('
# this will raise a RuntimeError when join_roboparty returns a falsy value

join_roboparty and puts 'robotz party hard :)'
# this will only output the message if join_roboparty returns a truthy value

I hope that clarifies everything you need to know about these operators. It takes a bit of getting used to, because it differs from the way other languages handle it. But once you know how to use the different options, you've got some powerful tools at hand.

我希望这能使你对这些操作符的了解更加清晰。它需要一点时间来适应,因为它不同于其他语言处理它的方式。但是一旦你知道如何使用不同的选项,你就有了一些强大的工具。

#2


1  

Both values are 'truthy' (in Ruby everything that isn't nil or false is truthy), so in all cases the second value is returned. On the contrary, if you use 'or', first value will be returned:

这两个值都是“truthy”(在Ruby中,所有非nil或false的值都是truthy),因此在所有情况下都返回第二个值。相反,如果使用'or',则返回第一个值:

1 || 0 #=> 1
0 || 1 #=> 0

#3


0  

In Ruby both 0 and 1 is truth value. (Only nil and false are false value)

在Ruby中,0和1都是真值。(只有nil和false是假值)

If both operands are truth value, and, && returns the last value.

如果两个操作数都是真值,并返回最后一个值。

#1


6  

As opposed to other languages like C, in Ruby all values except for nil and false are considered “truthy”. This means, that all these values behave like true in the context of a boolean expression.

与其他语言如C不同,在Ruby中除了nil和false之外的所有值都被认为是“真实的”。这意味着,所有这些值在布尔表达式的上下文中都表现为true。

Ruby's boolean operators will not return true or false. Instead, they return the first operand that causes the evaluation of the condition to be complete (also known as short-circuit evaluation). For boolean and that means, it will either return the first “falsy” operand or the last one:

Ruby的布尔运算符不会返回真或假。相反,它们返回第一个操作数,从而导致对条件的评估完成(也称为短路评估)。对于布尔值,它要么返回第一个“falsy”操作数,要么返回最后一个:

false && 1    # => false     (falsy)
nil   && 1    # => nil       (falsy)
false && nil  # => false     (falsy)
1     && 2    # => 2         (truthy)

For boolean or that means, it will either return the first “truthy” operand or the last one:

对于布尔值,它要么返回第一个“truthy”操作数,要么返回最后一个:

false || 1    # => 1         (truthy)
nil   || 1    # => 1         (truthy)
false || nil  # => nil       (falsy)
1     || 2    # => 1         (truthy)

This allows for some interesting constructs. It is a very common pattern to use || to set default values, for example:

这允许一些有趣的结构。使用||设置默认值是一种非常常见的模式,例如:

def hello(name)
  name = name || 'generic humanoid'
  puts "Hello, #{name}!"
end

hello(nil)    # Hello, generic humanoid!
hello('Bob')  # Hello, Bob!

Another similar way to acheive the same thing is

另一种类似的方法是。

name || (name = 'generic humanoid')

With the added benefit that if name is truthy, no assignment is performed at all. There is even a shortcut for this assignment of default values:

附加的好处是,如果名称是真实的,则根本不执行任何赋值。甚至还有一个分配默认值的快捷方式:

name ||= 'generic humanoid'

If you paid careful attention you will have noticed that this may cause some trouble, if one valid value is false:

如果你仔细注意,你会发现这可能会引起一些麻烦,如果一个有效值是假的:

destroy_humans = nil
destroy_humans ||= true
destroy_humans
#=> true

destroy_humans = false
destroy_humans ||= true
destroy_humans
#=> true, OMG run!

This is rarely the desired effect. So if you know that the values can only be a String or nil, using || and ||= is fine. If the variable can be false, you have to be more verbose:

这很少是期望的效果。如果你知道值只能是一个字符串或nil,使用||和||=就可以了。如果变量可以为false,则必须更详细:

destroy_humans = nil
destroy_humans = true if destroy_humans.nil?
destroy_humans
#=> true

destroy_humans = false
destroy_humans = true if destroy_humans.nil?
destroy_humans
#=> false, extinction of humanity digressed!

That was close! But wait, there is another caveat – specifically with the usage of and and or. These should never be used for boolean expressions, because they have very low operator precedence. That means they will be evaluated last. Consider the following examples:

这是近了!但是,等等,还有另外一个警告——特别是关于and和or的用法。这些不应该用于布尔表达式,因为它们的运算符优先级很低。这意味着它们将在最后进行评估。考虑下面的例子:

is_human = true
is_zombie = false
destroy_human = is_human && is_zombie
destroy_human
#=> false

is_human = true
is_zombie = false
destroy_human = is_human and is_zombie
destroy_human
#=> true, Waaaah but I'm not a zombie!

Let me add some parentheses to clarify what's happening here:

让我加一些括号来说明这里发生了什么

destroy_human = is_human && is_zombie
# equivalent to
destroy_human = (is_human && is_zombie)

destroy_human = is_human and is_zombie
# equivalent to
(destroy_human = is_human) and is_zombie

So and and or are really just useful as “control-flow operators”, for example:

因此,或者实际上只是作为“控制流操作符”有用,例如:

join_roboparty or fail 'forever alone :('
# this will raise a RuntimeError when join_roboparty returns a falsy value

join_roboparty and puts 'robotz party hard :)'
# this will only output the message if join_roboparty returns a truthy value

I hope that clarifies everything you need to know about these operators. It takes a bit of getting used to, because it differs from the way other languages handle it. But once you know how to use the different options, you've got some powerful tools at hand.

我希望这能使你对这些操作符的了解更加清晰。它需要一点时间来适应,因为它不同于其他语言处理它的方式。但是一旦你知道如何使用不同的选项,你就有了一些强大的工具。

#2


1  

Both values are 'truthy' (in Ruby everything that isn't nil or false is truthy), so in all cases the second value is returned. On the contrary, if you use 'or', first value will be returned:

这两个值都是“truthy”(在Ruby中,所有非nil或false的值都是truthy),因此在所有情况下都返回第二个值。相反,如果使用'or',则返回第一个值:

1 || 0 #=> 1
0 || 1 #=> 0

#3


0  

In Ruby both 0 and 1 is truth value. (Only nil and false are false value)

在Ruby中,0和1都是真值。(只有nil和false是假值)

If both operands are truth value, and, && returns the last value.

如果两个操作数都是真值,并返回最后一个值。