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)
我正在尝试将数字文字与可以 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)