Ruby的&&运算符

brs*_*slv 3 ruby conditional iterator

在PHP中,这评估为true:

$a = 1
$b = 2

var_dump($a && $b); // true
Run Code Online (Sandbox Code Playgroud)

在ruby中,这评估为2:

a = 1
b = 2
p a && b # 2
Run Code Online (Sandbox Code Playgroud)

为什么ruby返回最后一个语句的值(当第一个为真且第二个为真时)并且不返回布尔值?

我有两个数组,我用外部迭代器迭代它们:

a = [1,2,3].to_enum
b = [5,6,7].to_enum
c = []

begin
  while a_next = a.next && b_next = b.next
    result = a_next + b_next
    p "a[x] + b[x] = c[x] = #{a_next} + #{b_next} = #{result}"
    c << result
  end
rescue 
  p c
end
Run Code Online (Sandbox Code Playgroud)

条件:while a_next = a.next && b_next = b.next集合a_next = b_next(我认为第一个问题似乎与此行为有关).但是当我包装两个&&操作数时,它按预期工作:(a_next = a.next) && (b_next = b.next).

Car*_*and 6

Truthy和Falsy与truefalse

考虑

    3 && 4     #=> 4 
    3 && false #=> false 
  nil && 4     #=> nil 
false && nil   #=> false 

    3 || 4     #=> 3 
    3 || false #=> 3 
  nil || 4     #=> 4 
false || nil   #=> nil 
Run Code Online (Sandbox Code Playgroud)

回想一下,在Ruby中,falsenil以逻辑方式false("falsy")进行评估,其他一切评估为逻辑true("truthy").因此,通常不需要将伪值转换为值false或将truthy值转换为true.我们可以写一下,例如,

3 ? "happy" : "sad"
  #=> "happy"
nil ? "happy" : "sad"
  #=> "sad"
Run Code Online (Sandbox Code Playgroud)

将Truthy和Falsy转换为truefalse

如果你坚持,你可以转换和使用双惊叹技巧truthyfalsey值:truefalse

!!3 => !(!3) => !(false) => true
!!nil => !(!nil) => !(true) => false
Run Code Online (Sandbox Code Playgroud)

随着贸易的技巧&&||

拥有&&||定义它们的方式通常非常方便.例如,如果h是哈希,假设我们写

h[k] = (h[k] || []) << 3
Run Code Online (Sandbox Code Playgroud)

如果h没有钥匙k,h[k] #=> nil,所以表达式简化为

h[k] = [] << 3
  #=> [3]
Run Code Online (Sandbox Code Playgroud)

另一个例子是对arr整数或者数组的元素求和nil:

arr.reduce(0) { |t,n| t + (n || 0) }
Run Code Online (Sandbox Code Playgroud)

还有许多其他创造性的方法可以在Ruby中使用这两个操作符,如果它们只是返回true或者是不可能的false.

代码段

现在让我们转到您提到的代码段.

首先,你的救援条款有点分散注意力,而且while论证总是正确的,因此有点人为,所以让我们写下你所拥有的内容如下.

a = [1,2,3].to_enum
  #=> #<Enumerator: [1, 2, 3]:each> 
b = [5,6,7].to_enum
  #=> #<Enumerator: [5, 6, 7]:each> 
c = []
loop do
  a_next = a.next
  b_next = b.next
  result = a_next + b_next
  p "a[x] + b[x] = c[x] = #{a_next} + #{b_next} = #{result}"
  c << result
end
  # "a[x] + b[x] = c[x] = 1 + 5 = 6"
  # "a[x] + b[x] = c[x] = 2 + 6 = 8"
  # "a[x] + b[x] = c[x] = 3 + 7 = 10"
p c
  #=> [1, 2, 3] 
Run Code Online (Sandbox Code Playgroud)

在枚举a.next所有元素之后执行时a,它将引发StopIteration异常(参见Enumerator#next).我选择的理由内核#环while是前者的手柄StopIteration通过终止循环的例外.因此,不需要救援.(顺便说一句,如果你做了救援while,你想要rescue StopIteration,而不是拯救所有例外.)


Ama*_*dan 5

这里有几个方面.

为什么ruby返回最后一个语句的值(当第一个为真且第二个为真时)并且不返回布尔值?

因为这种方式更有用.事实上,这种语义非常有用,PHP 7添加了它(但作为一个新的运算符??).在Ruby中,就像在PHP中一样,所有值都是真实的或虚假的.与PHP不同,Ruby对此有一个更严格的想法:只有false而且nil是假的,其他一切都是真的.这允许您轻松提供默认值:

name = options[:name] || "John Doe"
Run Code Online (Sandbox Code Playgroud)

如果options[:name]没有找到并返回nil,则该部分是假的,并且||将返回右侧; 否则,options[:name]将被退回.

在大多数情况下,您不需要布尔值,因为真实性或虚假性就足够了.如果你真的想要一个布尔值,例如为了不泄露私人信息,这个习惯用法!!value很常见:

def has_name?
  !!(self.name || self.nickname)
end
Run Code Online (Sandbox Code Playgroud)

!(否定)的结果总是布尔值; 如果你否定了两次,你就会将真实性转化为true虚假性false.

最后,

那个错误我是在病情的事情while- while a_next = a.next && b_next = b.next-这样写的,它总是将a_next = b_next(第一个问题似乎与这种行为,我认为).但是,当我包装两个&&操作数时 - 它按预期工作 - (a_next = a.next) && (b_next = b.next) # works ok.

然后你需要包装它们.这是由于运算符优先级,并且在设计上就像这样工作,因为写入更为正常

blue_green = colour == :blue || colour == :green
Run Code Online (Sandbox Code Playgroud)

blue_green = (colour == :blue || colour == :green)
Run Code Online (Sandbox Code Playgroud)

还有另一组布尔运算符实际上是按照你的建议工作的,唯一的区别是优先级,所以你可以编写它并让它工作:

while a_next = a.next and b_next = b.next
Run Code Online (Sandbox Code Playgroud)

它完全相同

while (a_next = a.next) && (b_next = b.next)
Run Code Online (Sandbox Code Playgroud)

但是警告:使用andor运算符代替&&||不正确是一个常见的错误,许多样式指南直接禁止它们(它们在此上下文中有用- 在循环条件内分配 - 而且可以用括号代替).例如:

andor关键字都被禁止.这不值得.总是使用&&||不是.