Comment puis-je vérifier si une variable est définie dans Ruby? Existe-t-il une issetméthode de type disponible?
Comment puis-je vérifier si une variable est définie dans Ruby? Existe-t-il une issetmé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 nils'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 nilque 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_varlorsqu'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
method2revient toujours nil. La première fois que vous appelez method1, la @xvariable n'est pas définie - elle method2sera donc exécutée. et method2se 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 method2sera 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
unlessdé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 ifbloc 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 methodet 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
nilest initialisée.