Ruby: оператор безопасной навигации, неопределенный метод `call`
Я пытаюсь сравнить числовой литерал с возвращаемым значением функции, которая может вернуть 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. Я путал рельсы try
синтаксис с синтаксисом оператора безопасной навигации.
2 ответа
Это прекрасно работает в Ruby 2.3+:
unreliable&.> 10
Например:
[-5, 0, nil, 5].each do |unreliable|
p unreliable&.> 0
end
# false
# false
# nil
# true
Как вы это попробовали, Руби ожидает 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
ожидает символ).
Я подозреваю, что это связано с причудами, позволяющими существовать только одному экземпляру для каждого
Numeric
Нет, это не имеет к этому никакого отношения.
foo.(bar)
является синтаксическим сахаром для
foo.call(bar)
Ergo,
foo&.(bar)
является синтаксическим сахаром для
foo&.call(bar)
Итак, ваш код:
unreliable&.(:>, 10)
является синтаксическим сахаром для
unreliable&.call(:>, 10)
Я не уверен, кто сказал вам, что оператор безопасной навигации принимает сообщение в качестве символьного аргумента. Весь смысл оператора безопасной навигации состоит в том, что у вас есть только тривиальные синтаксические издержки, если добавить один символ, &
напротив .
и выражение в противном случае остается неизменным.
Так,
unreliable > 10
который так же, как
unreliable.>(10)
просто становится
unreliable&.>(10)