I am trying to compare a number literal with the return value of a function that could return nil or a numeric. Consider this:
def unreliable
[nil, 42].sample
end
unreliable > 10
This will blow up 50% of the time with NoMethodError: undefined method '>' for nil:NilClass. So I tried this:
unreliable&.(:>, 10)
That approach does the nil guarding I expect, but I get this when unreliable returns 42:
NoMethodError: undefined method `call' for 42:Fixnum
I suspect this has to do with the quirks of allowing only one instance to exist for each Numeric, see here. And I know I can do this:
foo = unreliable
foo && foo > 10
But is there a way to use the safe navigation operator with a numeric and :>, :<, :==, :+, :-, :/, :*, etc?
Edit: The focus on Numeric in my question is a red herring. See @Jörg's answer. I was confusing Rails's try syntax with the safe-navigation operator's syntax.
This works fine in Ruby 2.3+ :
unreliable&.> 10
For example :
[-5, 0, nil, 5].each do |unreliable|
p unreliable&.> 0
end
# false
# false
# nil
# true
The way you tried it, Ruby expects unreliable to be a callable object such as a 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]
With the safe-navigation operator, there's no need to put parens and the method should be a method name, not a symbol (Rails' try expects a symbol).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With