Ani*_*mar 2 ruby logical-operators
最近我开始学习Ruby.我正在练习逻辑运算符irb,我得到了这些结果,我不明白.你能帮我澄清一下这些例子吗?
1 and 0
#=> 0
0 and 1
#=> 1
0 && 1
#=> 1
Run Code Online (Sandbox Code Playgroud)
与其他语言(如C)相反,在Ruby中除了nil和之外的所有值都false被认为是"真实的".这意味着,所有这些值的行为都类似于true布尔表达式的上下文.
Ruby的布尔运算符不会返回true或false.相反,它们返回第一个操作数,导致条件评估完成(也称为短路评估).对于布尔值,这意味着,它将返回第一个"falsy"操作数或最后一个:
false && 1 # => false (falsy)
nil && 1 # => nil (falsy)
false && nil # => false (falsy)
1 && 2 # => 2 (truthy)
Run Code Online (Sandbox Code Playgroud)
对于布尔值或者意味着,它将返回第一个"truthy"操作数或最后一个:
false || 1 # => 1 (truthy)
nil || 1 # => 1 (truthy)
false || nil # => nil (falsy)
1 || 2 # => 1 (truthy)
Run Code Online (Sandbox Code Playgroud)
这允许一些有趣的结构.这是||用于设置默认值的非常常见的模式,例如:
def hello(name)
name = name || 'generic humanoid'
puts "Hello, #{name}!"
end
hello(nil) # Hello, generic humanoid!
hello('Bob') # Hello, Bob!
Run Code Online (Sandbox Code Playgroud)
另一种类似的方法来实现同样的事情
name || (name = 'generic humanoid')
Run Code Online (Sandbox Code Playgroud)
额外的好处是,如果名称真实,则根本不执行任何分配.这种默认值分配甚至有一个快捷方式:
name ||= 'generic humanoid'
Run Code Online (Sandbox Code Playgroud)
如果你小心注意,你会注意到这可能会造成一些麻烦,如果一个有效值是false:
destroy_humans = nil
destroy_humans ||= true
destroy_humans
#=> true
destroy_humans = false
destroy_humans ||= true
destroy_humans
#=> true, OMG run!
Run Code Online (Sandbox Code Playgroud)
这很少是预期的效果.所以如果你知道这些值只能是a String或者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!
Run Code Online (Sandbox Code Playgroud)
那很接近!但是等等,还有另一个警告 - 特别是使用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!
Run Code Online (Sandbox Code Playgroud)
让我添加一些括号来澄清这里发生的事情:
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
Run Code Online (Sandbox Code Playgroud)
所以and和/或者实际上只是作为"控制流操作符"有用,例如:
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
Run Code Online (Sandbox Code Playgroud)
我希望能澄清您需要了解的有关这些运营商的所有信息.它需要一些习惯,因为它不同于其他语言处理它的方式.但是一旦你知道如何使用不同的选项,你就会得到一些强大的工具.