Ruby2.3之前的版本与安全导航运算符(& ;.或"&&-点")等效吗? [英] What is the pre-Ruby2.3 equivalent to the safe navigation operator (&. or "ampersand-dot")?
问题描述
我能找到的每个问题的答案(第一季度,Q2 )新的安全导航运算符(&.
)错误地声明obj&.foo
等效于obj && obj.foo
.
The answers to every question I can find (Q1, Q2) regarding Ruby's new safe navigation operator (&.
) wrongly declare that obj&.foo
is equivalent to obj && obj.foo
.
很容易证明这种等效是不正确的:
It's easy to demonstrate that this equivalence is incorrect:
obj = false
obj && obj.foo # => false
obj&.foo # => NoMethodError: undefined method `foo' for false:FalseClass
此外,存在多重评估的问题.用具有副作用的表达式替换obj
时,表明仅在&&
表达式中,副作用才翻倍:
Further, there is the problem of multiple evaluation. Replacing obj
with an expression having side effects shows that the side effects are doubled only in the &&
expression:
def inc() @x += 1 end
@x = 0
inc && inc.itself # => 2
@x = 0
inc&.itself # => 1
避免出现这些问题的,与obj&.foo
相同的最简洁的2.3版之前是什么?
What is the most concise pre-2.3 equivalent to obj&.foo
that avoids these issues?
推荐答案
The safe navigation operator in Ruby 2.3 works almost exactly the same as the try!
method added by ActiveSupport, minus its block handling.
它的简化版可能看起来像这样:
A simplified version of that could look like this:
class Object
def try(method, *args, &block)
return nil if self.nil?
public_send(method, *args, &block)
end
end
您可以像这样使用
obj.try(:foo).try(:each){|i| puts i}
此try
方法实现了安全导航操作符的各种详细信息,包括:
This try
method implements various details of the safe navigation operator, including:
- 如果接收方为
nil
,则始终返回nil
,而不管nil
是否实际实现了所查询的方法. - 如果非
nil
接收者不支持该方法,则会引发NoMethodError
. - 它不会吞下方法调用上的任何异常.
- It always returns
nil
if the receiver isnil
, regardless of whethernil
actually implements the queried method or not. - It raises a
NoMethodError
if the non-nil
receiver doesn't support the method. - It doesn't swallow any exceptions on method calls.
由于语言语义上的差异,它不能(完全)实现真正的安全导航运算符的其他功能,包括:
Due to differences in language semantics, it can not (fully) implement other features of the real safe navigation operator, including:
-
与安全导航运算符相比,我们的
try
方法始终评估其他参数.考虑这个例子
Our
try
method always evaluates additional arguments, in contrast to the safe navigation operator. Consider this example
nil&.foo(bar())
在这里,不评估bar()
.当使用我们的try
方法作为
Here, bar()
is not evaluated. When using our try
method as
nil.try(:foo, bar())
我们总是首先调用bar
方法,无论以后是否使用它调用foo
.
we always call the bar
method first, regardless of whether we later call foo
with it or not.
请注意,当在生产环境中实际实现此代码时,应查看改进,而不是修补核心类.
Note that when actually implementing this code in production, you should have a look at Refinements instead of patching core classes.
这篇关于Ruby2.3之前的版本与安全导航运算符(& ;.或"&&-点")等效吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!