Je cherche un moyen concis de vérifier une valeur pour voir si elle est nulle ou nulle. Actuellement, je fais quelque chose comme:
if (!val || val == 0)
# Is nil or zero
end
Mais cela semble très maladroit.
Les objets ont un nil? méthode .
if val.nil? || val == 0
[do something]
end
Ou, pour une seule instruction:
[do something] if val.nil? || val == 0
Si vous aimez vraiment les noms de méthodes avec des points d'interrogation à la fin:
if val.nil? || val.zero?
# do stuff
end
Votre solution est satisfaisante, de même que quelques-unes des autres solutions.
Ruby peut vous aider à faire tout ce que vous voulez, si vous ne faites pas attention.
Tout d'abord, je pense que c'est à peu près le moyen le plus concis de vérifier cette condition particulière.
Deuxièmement, pour moi, il s’agit d’une odeur de code qui indique une faille potentielle dans votre conception. En règle générale, zéro et zéro ne doivent pas signifier la même chose. Si possible, essayez d’éliminer la possibilité que val soit nul avant de frapper ce code, soit en vérifiant cela au début de la méthode, soit en utilisant un autre mécanisme.
Vous avez peut-être une raison tout à fait légitime de faire cela, auquel cas je pense que votre code est bon, mais au moins, je penserais à essayer de supprimer si possible le chèque nul.
À partir de Ruby 2.3.0, vous pouvez combiner l'opérateur de navigation sécurisée (&.
) avec Numeric#nonzero?
. &.
renvoie nil
si l'instance était nil
et nonzero?
- si le nombre était 0
:
unless val&.nonzero?
# Is nil or zero
end
Ou postfix:
do_something unless val&.nonzero?
Vous pouvez utiliser Object.nil? tester spécifiquement pour néant (et ne pas se laisser prendre entre faux et néant). Vous pouvez aussi monkey-patcher une méthode dans 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
Cela n’est pas recommandé, car les modifications apportées à Object sont difficiles à retracer pour vos collègues et peuvent rendre votre code imprévisible pour les autres.
nil.to_i renvoie zéro, je fais donc souvent ceci:
val.to_i.zero?
Cependant, vous obtiendrez une exception si val est un objet qui ne répond pas à #to_i.
Je crois que votre code est incorrect. il testera en fait trois valeurs: nil
,false
, et zéro. Cela est dû au fait que l'expression !val
est true pour toutes les valeurs false, qui dans Ruby sont nil
et false
.
Le mieux que je puisse trouver en ce moment est
if val == nil || val == 0
# do stuff
end
Ce qui, bien sûr, n’est pas très intelligent, mais très clair.
Ma solution utilise également les raffinements, moins les conditions.
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 le fait via des méthodes de requête attributaires, où, outre false et nil, 0 et "" sont également évaluées sur false
if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation
Cependant, il a sa part de détracteurs. http://www.joegrossberg.com/archives/002995.html
Pour être aussi idiomatique que possible, je suggérerais ceci.
if val.nil? or val == 0
# Do something
end
Parce que:
Le plus court et le meilleur moyen devrait être
if val&.>(0)
# do something
end
Pour val&.>(0)
it, la valeur renvoyée est nil lorsque val est nul, car> est également une méthode, nil est égal à false en Ruby. Il retourne false lorsque val == 0
.
C'est très concis:
if (val || 0) == 0
# Is nil, false, or zero.
end
Cela fonctionne tant que cela ne vous dérange pas de traiter false
de la même manière que nil
. Dans les projets sur lesquels j'ai travaillé, cette distinction n'a d'importance que de temps en temps. Le reste du temps, je préfère personnellement sauter .nil?
et avoir un code légèrement plus court.
[ Mise à jour : Je n'écris plus ce genre de chose. Cela fonctionne mais est trop cryptique. J'ai essayé de réparer mes erreurs en changeant les quelques endroits où je les ai faits.]
En passant, je n’ai pas utilisé .zero?
car cela déclenche une exception si val
est, par exemple, une chaîne. Mais .zero?
conviendrait si vous savez que ce n'est pas le cas.
Au lieu de patcher une classe, vous pouvez utiliser des améliorations à partir de Ruby 2.1. Les raffinements ressemblent au patchage des singes; en cela, ils vous permettent de modifier la classe, mais la modification est limitée à la portée dans laquelle vous souhaitez l'utiliser.
C’est exagéré si vous voulez effectuer cette vérification une fois, mais si vous vous répétez, c’est une excellente alternative au patchage des singes.
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
Les améliorations ont été modifiées à la dernière minute pour être intégrées au fichier. Donc, des exemples précédents peuvent avoir montré cela, ce qui ne fonctionnera pas.
class Car
using NilOrZero
end
Vous pouvez utiliser case
si vous aimez:
case val with nil, 0
# do stuff
end
Ensuite, vous pouvez utiliser tout ce qui fonctionne avec ===
, ce qui est parfois agréable. Ou faire quelque chose comme ça:
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
Ce n'est pas vraiment une bonne POO, mais c'est très flexible et ça marche. Mes if
s finissent généralement par case
s de toute façon.
Bien sûr, le type Enum.any?
/Enum.include?
fonctionne aussi ... si vous voulez être vraiment crypté:
if [0, nil].include? val
#do stuff
end
La bonne chose à faire est bien sûr de définir une méthode ou une fonction. Ou, si vous devez faire la même chose avec beaucoup de valeurs, utilisez une combinaison de ces itérateurs de Nice.
Ceci a la valeur true pour nil et zéro: nil.to_s.to_d == 0
unless (val || 0).zero?
# do stufff
end
J'aime beaucoup la méthode blank?
de Rails pour ce genre de choses, mais elle ne renverra pas true
pour 0
. Vous pouvez donc ajouter votre méthode:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
Et il vérifiera si une valeur est nulle ou 0:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
Je traite cela en définissant un "est?" méthode, que je peux ensuite mettre en œuvre différemment sur différentes classes. Donc pour Array, "is?" signifie "taille> 0"; pour Fixnum, cela signifie "self! = 0"; pour String cela signifie "self! = ''". NilClass, bien sûr, définit "is?" comme revenant à zéro.