不检查`||`,`!a || a.method`不能用多个变量来完成

Nil check in `||`, `!a || a.method` can't be done with multiple variables

例如,如果我们要检查一个数组是nil还是空,我们可以这样写:

if !a || a.empty?
    puts "nil or empty!"
end
#-> OK

但是,如果我们想用同样的方式检查两个数组,就会出现错误:

if !a || !b || a.empty? || b.empty?
    puts "nil or empty!"
end
#-> Error, `undefined method 'empty?' for Nil`
#          in the expression `a.empty?`

交换 !ba.empty? 的位置没有帮助,但不同的地方被指向错误:

if !a || a.empty? || !b || b.empty?
    puts "nil or empty!"
end
#-> Still error, `undefined method 'empty?' for Nil`
#                but this error is in the expression `b.empty?`

为什么在这种(多变量的)情况下,当 a.empty?b.empty? 被调用时,编译器无法分别推断出 ab 非零?

完整的可重现代码如下。

def foo (flag)
    if flag
        [] of Int32
    else
        nil
    end
end

# note, foo returns `Array(T) | Nil`
a = foo(true)
b = foo(true)

if !a || a.empty?
    puts "nil or empty!"
end
#-> OK

if !a || !b || a.empty? || b.empty?
    puts "nil or empty!"
end
#-> Error, `undefined method 'empty?' for Nil`
#          in the expression `a.empty?`

if !a || a.empty? || !b || b.empty?
    puts "nil or empty!"
end
#-> Still error, `undefined method 'empty?' for Nil`
#                but this error is in the expression `b.empty?`

这似乎是一个编译器错误。

但是您可以将条件放在括号中使其生效:(!a || a.empty?) || (!b || b.empty?)

这不是错误。

a || b || c || d

解析为:

(((a || b) || c) || d)

所以在你的例子中你有:

!a || !b || a.empty? || b.empty?

这意味着它是

(((!a || !b) || a.empty?) || b.empty?)

所以来自:

!a || !b

你无法推断出关于 ab 的任何信息。

如果您添加括号,它会起作用:

if !a || (!b || (a.empty? || b.empty?))