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

3

我正在尝试将数字文字与可能返回nil或数字的函数的返回值进行比较。考虑以下内容:

def unreliable
  [nil, 42].sample  
end

unreliable > 10

这段代码有50%的几率出现NoMethodError: undefined method '>' for nil:NilClass错误。所以我尝试了以下方法:

unreliable&.(:>, 10)

这种方法可以进行nil保护,但是当unreliable返回42时,会出现以下情况:

NoMethodError: undefined method `call' for 42:Fixnum

我猜想这与只允许每个Numeric实例存在一个实例的怪癖有关,请参见此处。我知道我可以这样做:

foo = unreliable
foo && foo > 10

但是,有没有办法在数字和 :>, :<, :==, :+, :-, :/, :* 等操作符中使用安全导航运算符呢?
编辑:我的问题中关注的 Numeric 是一个红鱼,参见 @Jörg 的答案。我混淆了 Rails 的 try 语法和安全导航运算符的语法。

啊哈,好的 - 对此我很抱歉。我想表达感激之情,并让大家知道这个答案解决了我的问题,但我明白你的意思,以后我会这样做的。 - Ethan Kent
@CarySwoveland 这里的答案完全没问题。别试图去管那些最好不要碰的事情。 - Darth Egregious
@Fuser97381,我说过答案不够好吗?这是一个很棒的答案。如果这是我的答案,我也会给出同样的建议。 - Cary Swoveland
2个回答

5

这在 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期望符号)。

记录一下,p unreliable&.send( :>, 0)也可以工作。虽然很小,但我倾向于编写您的操作行p unreliable&.> 0,因为句点的存在表明您没有使用语法糖。 - Cary Swoveland
@CarySwoveland 那么在&.>之间没有空格吗?我很乐意听取建议,因为我找不到任何令人愉悦的格式化该行的方式。 - Eric Duminil
这是我的倾斜。当然,你可以写p unreliable&.>(0),但如果你在同一行后面有其他内容的话,我才会考虑使用它(p unreliable&.>(0) && ...)。 - Cary Swoveland
@CarySwoveland:谢谢。通常我发现安全航行操作符写起来和读起来都不太愉快。:-/ - Eric Duminil
我也是,但或许当我们使用它更多时就会有不同的感受了。 - Cary Swoveland
显示剩余2条评论

1

我怀疑这与只允许每个“数字”存在一个实例的怪异之处有关

不,这完全与此无关。

foo.(bar)

"

"是语法糖,表示段落。

foo.call(bar)

因此,
foo&.(bar)

"

" 是 "<\/p>" 的语法糖。

foo&.call(bar)

所以,你的代码:

unreliable&.(:>, 10)

语法糖,用于表示:

unreliable&.call(:>, 10)

我不确定是谁告诉你安全导航运算符将消息作为符号参数。安全导航运算符的整个重点在于,只需在“.”前面添加一个字符“&”,表达式就可以保持不变,从而只增加了微不足道的语法开销。请注意,保留HTML标签。
因此,
unreliable > 10

这与

相同。

unreliable.>(10)

简单地变成了

unreliable&.>(10)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接