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)
Другие вопросы по тегам