Лучший рубин идиома для "ноль или ноль" - PullRequest
72 голосов
/ 16 октября 2008

Я ищу краткий способ проверить значение, чтобы увидеть, является ли оно ноль или ноль. В настоящее время я делаю что-то вроде:

if (!val || val == 0)
  # Is nil or zero
end

Но это кажется очень неуклюжим.

Ответы [ 21 ]

65 голосов
/ 16 октября 2008

Объекты имеют ноль? метод .

if val.nil? || val == 0
  [do something]
end

Или только для одной инструкции:

[do something] if val.nil? || val == 0
31 голосов
/ 07 ноября 2008

Если вам действительно нравятся имена методов с вопросительными знаками в конце:


if val.nil? || val.zero?
  # do stuff
end

Ваше решение в порядке, как и некоторые другие решения.

Ruby может заставить вас искать красивый способ сделать все, если вы не будете осторожны.

29 голосов
/ 16 октября 2008

Прежде всего, я думаю, что это самый краткий способ проверить это конкретное состояние.

Во-вторых, для меня это запах кода, который указывает на потенциальный недостаток в вашем дизайне. Обычно ноль и ноль не должны означать одно и то же. Если возможно, вы должны попытаться исключить возможность того, что val будет равен nil, прежде чем вы попадете в этот код, либо проверив это в начале метода, либо каким-либо другим механизмом.

У вас может быть вполне законная причина сделать это, и в этом случае я думаю, что ваш код хорош, но я бы по крайней мере рассмотрел попытку избавиться от нулевой проверки, если это возможно.

24 голосов
/ 15 января 2016

Начиная с версии Ruby 2.3.0, вы можете комбинировать оператор безопасной навигации (&.) с Numeric#nonzero?. &. возвращает nil, если экземпляр был nil и nonzero? - если число было 0:

unless val&.nonzero?
  # Is nil or zero
end

Или постфикс:

do_something unless val&.nonzero?
9 голосов
/ 16 октября 2008

Вы можете использовать Object.nil? проверить на ноль специально (и не попасться между ложным и нулевым). Вы также можете прикрепить метод к объекту.

class Object
   def nil_or_zero?
     return (self.nil? or self == 0)
   end
end

my_object = MyClass.new
my_object.nil_or_zero?
==> false

Это не рекомендуется, поскольку изменения в Object трудны для отслеживания коллегами и могут сделать ваш код непредсказуемым для других.

4 голосов
/ 16 октября 2008

Я считаю, что ваш код неверен; фактически он будет проверять три значения: nil, false и ноль. Это связано с тем, что выражение !val имеет значение true для всех значений false, которые в Ruby равны nil и false.

Лучшее, что я могу придумать сейчас - это

if val == nil || val == 0
  # do stuff
end

Что, конечно, не очень умно, но (очень) понятно.

4 голосов
/ 06 ноября 2009

nil.to_i возвращает ноль, поэтому я часто делаю это:

val.to_i.zero?

Тем не менее, вы получите исключение, если val когда-либо является объектом, который не отвечает

3 голосов
/ 11 сентября 2018

В моем решении также используются уточнения минус условные выражения.

module Nothingness
  refine Numeric do
    alias_method :nothing?, :zero?
  end

  refine NilClass do
    alias_method :nothing?, :nil?
  end
end

using Nothingness

if val.nothing?
  # Do something
end
2 голосов
/ 16 октября 2008

Rails делает это с помощью методов запроса атрибутов, где в дополнение к false и nil 0 и "" также оцениваются как false.

if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation

Однако у него есть своя недоброжелательность. http://www.joegrossberg.com/archives/002995.html

2 голосов
/ 27 октября 2016

Самый короткий и лучший способ должен быть

if val&.>(0)
  # do something
end

Для val&.>(0) он возвращает nil, когда val равен nil, поскольку> в основном также является методом, равным false в ruby. Возвращается false когда val == 0.

...