这个逻辑AND运算符的作用是什么



在/rails/lib/rails.rb中,有一个使用逻辑&&运算符的习惯用法:

def root
application && application.config.root
end

这个成语的意思是什么?它似乎做了一些控制流,只返回application.config.root(如果应用程序存在(或类似的东西?

在ruby中,逻辑运算符是"懒惰";。

考虑以下内容:

def one
puts "Called method one"
false
end
def two
puts "Called method two"
true
end
puts "Calling one, then two:"
one && two
puts
puts "Calling two, then one:"
two && one

它给出以下输出:

Calling one, then two:
Called method one
Calling two, then one:
Called method two
Called method one

看到发生了什么吗?当它调用one并得到false时,它甚至没有麻烦调用方法two——因为它已经知道最终结果将是false。(false && false=false && true=false。(

现在让我们回顾一下您发布的原始代码:

def root
application && application.config.root
end

如果application == nil会发生什么?此代码甚至不需要评估右手边。由于CCD_ 10。

换句话说,这是一个安全的警卫。如果application == nil。它(不是确切地,但基本上(相当于写这个:

def root
return nil if application == nil

application.config.root
end

根据广泛使用的ruby样式指南,https://github.com/rubocop-hq/ruby-style-guide#if-作为修饰符,当你有一个单行体时,需要更喜欢使用修饰符if/unless。另一个好的选择是使用控制流&&/||(即您所询问的内容(。

# bad
if some_condition
do_something
end
# good
do_something if some_condition
# another good option
some_condition && do_something

避免NoMethodError

Ruby代码在对计算结果为nil的表达式或不#responsd_to的对象调用方法时,可能会抛出NoMethodError?一种特殊的方法。虽然较新版本的Ruby支持安全导航运算符来防止在NilClass实例上调用方法,但较旧的代码通常需要这种类型的构造来避免引发异常。

在peudocod:

define method "root":
if application does not evaluate to nil, then
invoke method config on application, then
invoke method root on application.config

在Ruby中>=2.3,您可能会将此方法重写为:

def root
application&.config.root
end

然而,在某些情况下,&.并不完全等同于obj && obj.method。前者只是防止在nil上调用方法。例如,如果application.nil?application.respond_to? :config都为false,那么在调用application&.config时使用安全导航器仍然会引发异常。

您的示例中的逻辑AND是否是必要的,因为应用程序变量是如何设置或使用的,只是一个遗留习惯用法,还是为了与早期版本的Ruby向后兼容而保留,您必须在Rails代码库中进行研究。在任何情况下,示例中的逻辑AND都可以防止NoMethodError异常

最新更新