Ruby: 安全导航运算符,未定义方法 `call`

Ruby: Safe-navigation operator, undefined method `call`

我正在尝试将数字文字与可以 return nil 或数字的函数的 return 值进行比较。考虑一下:

def unreliable
  [nil, 42].sample  
end

unreliable > 10

这将在 NoMethodError: undefined method '>' for nil:NilClass 的情况下炸毁 50% 的时间。所以我尝试了这个:

unreliable&.(:>, 10)

这种方法实现了我期望的 nil 保护,但我在 unreliable returns 42:

时得到了这个
NoMethodError: undefined method `call' for 42:Fixnum

我怀疑这与每个 Numeric 只允许一个实例存在的怪癖有关,参见 here。我知道我可以做到:

foo = unreliable
foo && foo > 10

但是有没有办法将安全导航运算符与数字和 :>:<:==:+:-:/:* 等?


编辑:我问题中 Numeric 的重点是转移注意力。请参阅@Jörg 的回答。我混淆了 Rails 的 try 语法和安全导航运算符的语法。

这在 Ruby 2.3+ 中工作正常:

unreliable&.> 10

例如:

[-5, 0, nil, 5].each do |unreliable|
  p unreliable&.> 0
end
# false
# false
# nil
# true

按照您尝试的方式,Ruby 期望 unreliable 是一个可调用对象,例如 Proc :

unreliable = Proc.new{ |*params| puts "unreliable has been called with #{params}" }
unreliable&.(:>, 10)
# unreliable has been called with [:>, 10]
unreliable.call(:>, 10)
# unreliable has been called with [:>, 10]
unreliable&.call(:>, 10)
# unreliable has been called with [:>, 10]
unreliable[:>, 10]
# unreliable has been called with [:>, 10]

有了安全导航运算符,就不需要括号了,方法应该是方法名,而不是符号(Rails' try 需要一个符号)。

I suspect this has to do with the quirks of allowing only one instance to exist for each Numeric

不,这与那个完全无关。

foo.(bar)

的语法糖
foo.call(bar)

因此,

foo&.(bar)

的语法糖
foo&.call(bar)

那么,您的代码:

unreliable&.(:>, 10)

的语法糖
unreliable&.call(:>, 10)

我不确定是谁告诉您安全导航运算符将消息作为符号参数。安全导航运算符的全部要点在于,您只需添加一个字符,即 . 前面的 &,语法开销很小,表达式在其他方面保持不变。

所以,

unreliable > 10

相同
unreliable.>(10)

简单地变成

unreliable&.>(10)