Я шукаю стислий спосіб перевірити значення на нуль чи нуль. В даний час я роблю щось на зразок:
if (!val || val == 0)
# Is nil or zero
end
Але це здається дуже незграбним.
Відповіді:
Об'єкти мають нуль? метод .
if val.nil? || val == 0
[do something]
end
Або лише для однієї інструкції:
[do something] if val.nil? || val == 0
or
не вимагає яких - або дужок тут, і буде читати повністю природно дослідне Rubyist. Єдині люди , які коли - або укушені ||
проти or
люди , які ніколи не запрограмовані Perl :)
val && val == 0
це краще.
Якщо вам дуже подобаються назви методів із знаками запитання в кінці:
if val.nil? || val.zero?
# do stuff
end
Ваше рішення прекрасне, як і деякі інші рішення.
Якщо ви не будете обережні, Ruby може змусити вас шукати гарний спосіб зробити все.
Починаючи з Ruby 2.3.0 і далі, ви можете поєднувати оператор безпечної навігації ( &.
) з Numeric#nonzero?
. &.
повертає, nil
якщо екземпляр був nil
і nonzero?
- якщо число було 0
:
unless val&.nonzero?
# Is nil or zero
end
Або постфікс:
do_something unless val&.nonzero?
unless val&.nonzero?
перекладається як "якщо вал рівний нулю чи нулю"
do_something if val&.nonzero?
(інакше, якщо val
немає nil
і не нуль).
По-перше, я думаю, що це найкоротший спосіб перевірити наявність певного стану.
По-друге, для мене це запах коду, який вказує на потенційний недолік у вашому дизайні. Взагалі нуль і нуль не повинні означати одне і те ж. Якщо це можливо, вам слід спробувати усунути ймовірність того, що val буде нульовим, перш ніж натиснути цей код, або перевіривши це на початку методу, або іншим механізмом.
У вас може бути цілком законна причина, щоб зробити це, і в цьому випадку я вважаю, що ваш код хороший, але я, принаймні, подумаю про те, щоб позбутися перевірки на нуль, якщо це можливо.
Ви можете використовувати 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
Це не рекомендується, оскільки зміни в Object важко відслідковувати колегам і можуть зробити ваш код непередбачуваним для інших.
nil?
завжди буде повертати false. nil?
повертає true лише для NilClass.
Object
, NilClass
і Numeric
. Object
повернуся false
, NilClass
повернуся true
і Numeric
повернуся zero?
.
nil.to_i повертає нуль, тому я часто роблю це:
val.to_i.zero?
Однак ви отримаєте виняток, якщо val коли-небудь є об'єктом, який не реагує_на #to_i.
"5".to_i == 5, but you're more or less right. Clever but doesn't actually work
Я вважаю, що ваш код неправильний; це буде насправді тест для трьох значень: 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
#attribute
, бо я не можу знайти нічого подібного.
Щоб бути якомога ідіоматичнішим, я б запропонував це.
if val.nil? or val == 0
# Do something
end
Оскільки:
Короткий і зрозумілий
[0, nil].include?(val)
val.in? [0,nil]
Повинен бути найкоротший і найкращий спосіб
if val&.>(0)
# do something
end
Бо val&.>(0)
він повертає nil, коли val дорівнює nil, оскільки> в основному також є методом, nil рівним false в ruby. Повертає false, коли val == 0
.
Я маю справу з цим, визначаючи "це?" метод, який я можу потім реалізувати по-різному в різних класах. Тож для Array "є?" означає "розмір> 0"; для Fixnum це означає "себе! = 0"; для String це означає "себе! = ''". NilClass, звичайно, визначає "це?" як просто повернення нуля.
Ви можете використовувати, 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
s в case
будь-якому випадку закінчуються як s.
Звичайно 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
І він перевірить, чи є якесь значення рівним нулю або 0:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
Замість того, щоб мавпа виправляла клас, ви можете використовувати уточнення, починаючи з 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
Це дуже стисло:
if (val || 0) == 0
# Is nil, false, or zero.
end
Це працює до тих пір, поки ви не проти лікувати false
те саме, що і nil
. У проектах, над якими я працював, ця відмінність має значення лише раз у раз. В інший час я особисто вважаю за краще пропускати .nil?
і маю трохи коротший код.
[ Оновлення : Я більше не пишу такого роду речі. Це працює, але занадто загадково. Я намагався виправити свої проступки, змінивши кілька місць, де я це робив.]
До речі, я не використовував, .zero?
оскільки це викликає виняток, якщо val
це, скажімо, рядок. Але .zero?
було б добре, якщо б ви знали, що це не так.
[edited]
Я думав, що якщо val
буде нуль, тоді цей вираз буде оцінювати як nil == 0
(і, отже, повертати false
). Однак, схоже, це насправді працює, хоча я не думаю, що це дуже читабельно.
Інше рішення:
if val.to_i == 0
# do stuff
end
"5".to_i == 5
, але ви більш-менш праві. Розумний, але насправді не працює.
val ||= 0
if val == 0
# do something here
end
val
потрібно зберігати? Ви обманюєте вхідні дані цим методом, і є кращі, менш руйнівні способи перевірки на нуль чи нуль.
false
?