Я ищу краткий способ проверить значение, чтобы узнать, равен ли он нулю или нулю. В настоящее время я делаю что-то вроде:
if (!val || val == 0)
# Is nil or zero
end
Но это кажется очень неуклюжим.
Я ищу краткий способ проверить значение, чтобы узнать, равен ли он нулю или нулю. В настоящее время я делаю что-то вроде:
if (!val || val == 0)
# Is nil or zero
end
Но это кажется очень неуклюжим.
Объекты имеют nil? Метод.
if val.nil? || val == 0
[do something]
end
Или для одной инструкции:
[do something] if val.nil? || val == 0
Если вам действительно нравятся имена методов с вопросительными знаками в конце:
if val.nil? || val.zero?
# do stuff
end
Ваше решение в порядке, как и некоторые другие решения.
Ruby может заставить вас искать прекрасный способ сделать все, если вы не будете осторожны.
Во-первых, я думаю, что о наиболее сжатом способе вы можете проверить это конкретное условие.
Во-вторых, для меня это запах кода, который указывает на потенциальный недостаток вашего дизайна. Как правило, ноль и ноль не должны означать одно и то же. Если возможно, вы должны попытаться исключить возможность того, что val будет равен нулю, прежде чем вы нажмете этот код, либо проверив это в начале метода, либо какой-либо другой механизм.
У вас может быть вполне законная причина сделать это, и в этом случае я думаю, что ваш код хорош, но я бы хотя бы подумал о попытке избавиться от проверки nil, если это возможно.
Начиная с Ruby 2.3.0, вы можете объединить безопасный навигационный оператор (&.
) с Numeric#nonzero?
. &.
возвращает nil
, если экземпляр был nil
и nonzero?
- если число было 0
:
unless val&.nonzero?
# Is nil or zero
end
Или постфикс:
do_something unless val&.nonzero?
Вы можете использовать Object.nil? для проверки нулевого значения (и не попадания между ложными и нулевыми значениями). Вы также можете обезвредить метод в Object.
class Object
def nil_or_zero?
return (self.nil? or self == 0)
end
end
my_object = MyClass.new
my_object.nil_or_zero?
==> false
Это не рекомендуется, так как изменения в объекте сложно отслеживать коллегам и могут сделать ваш код непредсказуемым для других.
nil.to_i возвращает ноль, поэтому я часто делаю это:
val.to_i.zero?
Однако вы получите исключение, если val всегда является объектом, который не отвечает_to #to_i.
Я считаю, что ваш код неверен; он фактически проверяет три значения: nil
, false
и ноль. Это происходит потому, что выражение !val
истинно для всех значений, которые являются ложными, что в Ruby составляет nil
и false
.
Лучшее, что я могу придумать прямо сейчас, это
if val == nil || val == 0
# do stuff
end
Что, конечно, не очень умно, но (очень) понятно.
Мое решение также использовать уточнения, минус условные.
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
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
Чтобы быть как можно более идиоматичным, я бы предложил это.
if val.nil? or val == 0
# Do something
end
Потому что:
Самый короткий и лучший способ должен быть
if val&.>(0)
# do something
end
Для val&.>(0)
он возвращает nil, когда val равен nil, поскольку> в основном также является методом, равным false в ruby. Возвращается false, когда val == 0
.
Короткие и четкие
[0, nil].include?(val)
Я занимаюсь этим, определяя "есть?" . метод, который затем я могу реализовать по-разному на разных классах. Итак, для Маре, "есть?" означает "размеp > 0"; для Fixnum это означает "self!= 0"; для String это означает "self! =". NilClass, конечно, определяет "есть?" как только возвращающ ноль.
Я только что удалил свой предыдущий ответ. Я неправильно понял вас и рекомендовал использовать метод #blank?
.
В любом случае, я бы расширил класс Object
и создал для этой цели метод.
Вы можете использовать case
, если хотите:
case val with nil, 0
# do stuff
end
Затем вы можете использовать все, что работает с ===
, что иногда бывает приятно. Или сделайте что-нибудь вроде этого:
not_valid = nil, 0
case val1 with *not_valid
# do stuff
end
#do other stuff
case val2 with *not_valid, false #Test for values that is nil, 0 or false
# do other other stuff
end
Это не совсем хороший ООП, но он очень гибкий и работает. Мой if
обычно заканчивается как case
.
Конечно, Enum.any?
/Enum.include?
тоже работает... если вам нравится быть загадочным:
if [0, nil].include? val
#do stuff
end
Правильная вещь - это, конечно, определить метод или функцию. Или, если вам нужно сделать то же самое со многими значениями, используйте комбинацию этих хороших итераторов.
Мне действительно нравится метод Rails blank?
для такого рода вещей, но он не вернет true
для 0
. Поэтому вы можете добавить свой метод:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
И он будет проверять, является ли какое-либо значение равным nil или 0:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
Это очень краткий:
if (val || 0) == 0
# Is nil, false, or zero.
end
Он работает до тех пор, пока вы не против обрабатывать false
так же, как nil
. В проектах, над которыми я работал, это различие имеет значение только время от времени. В остальное время я лично предпочитаю пропускать .nil?
и иметь несколько более короткий код.
[ Обновление: я больше ничего не пишу. Он работает, но слишком загадочен. Я попытался исправить свои проступки, изменив несколько мест, где я это сделал.]
Кстати, я не использовал .zero?
, так как это вызывает исключение, если val
есть, скажем, строка. Но .zero?
будет в порядке, если вы знаете, что это не так.
Вместо того, чтобы обезглавливать класс, вы можете использовать уточнения, начиная с Ruby 2.1. Уточнения подобны исправлениям обезьян; в этом случае они позволяют вам изменять класс, но модификация ограничивается областью, в которой вы хотите ее использовать.
Это слишком много, если вы хотите сделать эту проверку один раз, но если вы повторяете себя, это отличная альтернатива патчу обезьян.
module NilOrZero
refine Object do
def nil_or_zero?
nil? or zero?
end
end
end
using NilOrZero
class Car
def initialize(speed: 100)
puts speed.nil_or_zero?
end
end
car = Car.new # false
car = Car.new(speed: nil) # true
car = Car.new(speed: 0) # true
Уточнения были изменены в последнюю минуту для привязки к файлу. Поэтому более ранние примеры могли показать это, что не сработает.
class Car
using NilOrZero
end
Это значение true для nil и zero: nil.to_s.to_d == 0
unless (val || 0).zero?
# do stufff
end
Другое решение:
if val.to_i == 0
# do stuff
end
val ||= 0
if val == 0
# do something here
end