题:
当接收器为 &.
时,Ruby 安全导航操作符 ( nil
) 是否评估其参数?
例如:
logger&.log("Something important happened...")
"Something important happened..."
字符串在这里评估? 提前致谢。
为什么我要寻找这个问题的答案?
我的代码库中有如下代码:
logger.log("Something important happened. (#{Time.current})") if verbose
我的主要目标是消除 if verbose
的重复。每当我调用 log
时检查方法,因为很容易忘记它,而且您根本不会收到有关误用的通知。灵感来自 Tell, don't ask原则,
我已搬家
if verbose
检查内部 log
方法实现。class Logger
# ...
def log(message)
return unless verbose
# ...
end
end
def logger
@logger ||= Logger.new
end
logger.log("Something important happened. (#{Time.current})")
这种方法简化了我的代码,因为我已经解决了我的主要问题 - 我不需要记住放置 if verbose
每当我调用 log
方法,但我收到了另一个问题。
"Something important..."
字符串总是被评估,不管 verbose
是 true
或 false
.因此,我彻底改变了解决方案:
logger
返回 nil
当verbose
是 false
. log
前面调用。 def logger
@logger ||= Logger.new if verbose
end
logger&.log("Something important happened. (#{Time.current})")
结果我把最初的记不住if verbose
的问题换掉了检查内存 &.
调用。但是,无论如何,我认为这是一种改进,因为忘记使用安全导航操作符会引发
NoMethodError
,换句话说,通知 log
方法误用。所以现在,为了确保“安全导航运算符(operator)方法”实际上是解决我的问题的“更好”选择,
我需要确切地知道 Ruby 中的安全导航操作符是否在其接收器为
nil
时评估其参数。 .
最佳答案
引自 the syntax documentation对于安全导航运算符(operator):
&.
, called “safe navigation operator”, allows to skip method call when receiver isnil
. It returnsnil
and doesn't evaluate method's arguments if the call is skipped.
因此,您的
log
的论点如果 logger
不评估方法是 nil
当你把它称为logger&.log("something happened at #{Time.now}")
话虽如此,请注意 Ruby 核心记录器为您的确切问题提供了不同的解决方案,即避免在日志级别过高时评估潜在的昂贵参数。
Ruby 核心记录器实现了它的
add
方法是这样的(简化):class Logger
attr_accessor :level
def initialize(level)
@level = level.to_i
end
def add(severity, message = nil)
return unless severity >= level
message ||= yield
log_device.write(message)
end
def info(message = nil, &block)
add(1, message, &block)
end
end
然后您可以将其用作logger = Logger.new(1)
logger.info { "something happened at #{Time.now}" }
在这里,只有当日志级别足够高以至于实际使用消息时才会评估块。
关于ruby - 当接收器为零时,Ruby 安全导航运营商是否评估其参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63022321/