Comment puis-je vérifier si une variable est définie dans Ruby? Existe-t-il une isset
méthode de type disponible?
Comment puis-je vérifier si une variable est définie dans Ruby? Existe-t-il une isset
méthode de type disponible?
Réponses:
Utilisez le defined?
mot - clé ( documentation ). Il renverra une chaîne avec le type de l'élément, ou nil
s'il n'existe pas.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
Comme l'a souligné skalee: "Il convient de noter que la variable définie sur zéro est initialisée."
>> n = nil
>> defined? n
=> "local-variable"
||=
opérateur) ci-dessous.
defined?
renvoie toujours vrai pour une variable définie dans ce bloc!
defined?
celle -là qui retourne booléen?
!!defined?(object_name)
Ceci est utile si vous ne voulez rien faire s'il existe mais le créer s'il n'existe pas.
def get_var
@var ||= SomeClass.new()
end
Cela ne crée la nouvelle instance qu'une seule fois. Après cela, il continue de renvoyer la var.
||=
avec des valeurs booléennes, de peur de ressentir la douleur de la confusion.
nil
à moins que vous ne vouliez vraiment évaluer l'expression chaque fois qu'elle est appelée quand elle revientnil
var = (var or var.nil?)
La syntaxe correcte pour l'instruction ci-dessus est:
if (defined?(var)).nil? # will now return true or false
print "var is not defined\n".color(:red)
else
print "var is defined\n".color(:green)
end
en remplaçant ( var
) par votre variable. Cette syntaxe renverra une valeur vraie / fausse pour évaluation dans l'instruction if.
defined?(var) == nil
?
.nil?
est plus idiomatique, comme on dit. Il est plus "orienté objet" de demander à un objet s'il l'est plutôt nil
que d'utiliser un opérateur de comparaison. Aucun n'est difficile à lire, alors utilisez celui qui vous aide à expédier plus de produits.
defined?(your_var)
marchera. Selon ce que vous faites, vous pouvez également faire quelque chose commeyour_var.nil?
your_var.nil?
car il renvoie vrai ou faux et est beaucoup plus agréable à lire et à écrire que defined? var
. Merci pour cela.
your_var.nil?
entraînera une erreur: undefined local variable or method your_var
lorsqu'il n'est pas défini avant ...
Essayez "à moins que" au lieu de "si"
a = "apple"
# Note that b is not declared
c = nil
unless defined? a
puts "a is not defined"
end
unless defined? b
puts "b is not defined"
end
unless defined? c
puts "c is not defined"
end
Voici du code, rien de sorcier mais ça marche assez bien
require 'rubygems'
require 'rainbow'
if defined?(var).nil? # .nil? is optional but might make for clearer intent.
print "var is not defined\n".color(:red)
else
print "car is defined\n".color(:green)
end
De toute évidence, le code de coloration n'est pas nécessaire, juste une belle visualisation dans cet exemple de jouet.
nil?
est facultatif.
C'est la réponse clé: la defined?
méthode. La réponse acceptée ci-dessus illustre parfaitement cela.
Mais il y a un requin qui se cache sous les vagues ...
Considérez ce type de motif rubis commun:
def method1
@x ||= method2
end
def method2
nil
end
method2
revient toujours nil
. La première fois que vous appelez method1
, la @x
variable n'est pas définie - elle method2
sera donc exécutée. et method2
se mettra @x
à nil
. C'est bien, et tout va bien. Mais que se passe-t-il la deuxième fois que vous appelez method1
?
N'oubliez pas que @x a déjà été défini sur zéro. But method2
sera toujours exécuté à nouveau !! Si la méthode 2 est une entreprise coûteuse, ce n'est peut-être pas quelque chose que vous souhaitez.
Laissez la defined?
méthode venir à la rescousse - avec cette solution, ce cas particulier est traité - utilisez ce qui suit:
def method1
return @x if defined? @x
@x = method2
end
Le diable est dans les détails: mais vous pouvez échapper à ce requin qui se cache avec la defined?
méthode.
Tu peux essayer:
unless defined?(var)
#ruby code goes here
end
=> true
Parce qu'il renvoie un booléen.
SyntaxError: compile error (irb):2: syntax error, unexpected $end, expecting kEND
unless
déclaration semble trop compliqué
Comme de nombreux autres exemples le montrent, vous n'avez pas réellement besoin d'un booléen à partir d'une méthode pour faire des choix logiques en rubis. Ce serait une mauvaise forme de tout contraindre à un booléen, sauf si vous avez réellement besoin d'un booléen.
Mais si vous avez absolument besoin d'un booléen. Utilisation !! (bang bang) ou "falsy falsy révèle la vérité".
› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Pourquoi il n'est généralement pas avantageux de contraindre:
>> (!!defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red)) == (defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red))
=> true
Voici un exemple où cela est important car il repose sur la contrainte implicite de la valeur booléenne à sa représentation sous forme de chaîne.
>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil
Il convient de mentionner que l’utilisation de defined
pour vérifier si un champ spécifique est défini dans un hachage peut se comporter de manière inattendue:
var = {}
if defined? var['unknown']
puts 'this is unexpected'
end
# will output "this is unexpected"
La syntaxe est correcte ici, mais defined? var['unknown']
sera évaluée dans la chaîne "method"
, donc le if
bloc sera exécuté
edit: La notation correcte pour vérifier si une clé existe dans un hachage serait:
if var.key?('unknown')
Veuillez noter la distinction entre "défini" et "attribué".
$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"
x est défini même s'il n'est jamais attribué!
NameError Exception: undefined local variable or method
et j'étais confus quand la seule affectation / mention de la variable était dans un bloc if qui n'était pas touché.
En outre, vous pouvez vérifier s'il est défini dans une chaîne via une interpolation, si vous codez:
puts "Is array1 defined and what type is it? #{defined?(@array1)}"
Le système vous indiquera le type s'il est défini. S'il n'est pas défini, il renverra simplement un avertissement indiquant que la variable n'est pas initialisée.
J'espère que cela t'aides! :)
defined?
est génial, mais si vous êtes dans un environnement Rails, vous pouvez également l'utiliser try
, en particulier dans les cas où vous souhaitez vérifier un nom de variable dynamique:
foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo) # => 1
try(:bar) # => nil
try(my_foo) # => 1
try(my_bar) # => nil
nil
est initialisée.