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).