Vérification si une variable est définie?


518

Comment puis-je vérifier si une variable est définie dans Ruby? Existe-t-il une méthode de type isset disponible?

719

Utilisez le mot-clé defined? (documentation). Il retournera une chaîne avec le type de l'article, ou nil s'il n'existe pas. Comme skalee a commenté: "Il vaut la peine de noter que la variable qui est définie à zéro est initialisée."

>> n = nil 
>> defined? n 
=> "local-variable" 
+82

Il est à noter que la variable qui est définie sur 'nil' * est * initialisée. 16 févr.. 112011-02-16 13:18:34

+7

Si vous voulez définir une variable si elle n'existe pas et la laisser seule si c'est le cas, voir la réponse @ danmayer (impliquant l'opérateur '|| =') ci-dessous. 12 juil.. 112011-07-12 21:29:23

+2

C'est tellement rad. 09 mai. 142014-05-09 23:32:51

  0

Voici une autre bizarrerie que je peux .. Si vous définissez une variable dans un if-block pour lequel la condition n'est jamais remplie, 'defined?' Renvoie toujours vrai pour une variable définie dans ce bloc! 21 août. 162016-08-21 15:02:53


18

defined?(your_var) fonctionnera. En fonction de ce que vous faites, vous pouvez également faire quelque chose comme your_var.nil?

  0

+1 pour 'your_var.nil?', Car il retourne vrai de faux et est beaucoup plus agréable à lire et à écrire que 'défini? var'. Merci pour cela. 14 juil.. 132013-07-14 16:15:09

+25

'your_var.nil?' Entraînera une erreur: 'variable locale non définie ou méthode your_var' lorsqu'elle n'est pas définie auparavant ... 09 sept.. 132013-09-09 15:45:29


87

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 que la nouvelle instance une fois. Après cela, il ne fait que retourner le var.

+7

Ceci est très idiomatique Ruby aussi et très typique, d'ailleurs. 12 juil.. 112011-07-12 21:28:33

  0

Merci pour cette entrée! Je suis un débutant de ruby ​​/ rails et je suis tombé sur cette syntaxe hier soir, j'ai eu du mal à comprendre ce que cela signifiait. Ça a l'air très pratique! 07 nov.. 112011-11-07 10:35:35

  0

cela ne fonctionnera pas pour définir des constantes 24 nov.. 112011-11-24 14:52:18

+36

Il suffit de ne pas utiliser '|| =' avec des valeurs booléennes, de peur que vous vous sentez la douleur de confusion. 18 mai. 122012-05-18 06:27:07

+6

avec ce @AndrewMarshall dit, éviter cet idiome avec tout ce qui pourrait revenir 'nil' et à moins que vous * vraiment * voulez évaluer l'expression à chaque fois qu'il est appelé quand il ne retourne' nil' 19 nov.. 122012-11-19 23:58:52

  0

n'aime pas personnellement méthodes avec get_ sur le front (hé ce n'est pas Java :)), je l'appellerais simplement "var" et l'exposerais au monde extérieur de cette façon. Je le fais souvent pour cacher @variables et les par défaut sans avoir à passer par beaucoup de cerceaux. get_ se sent très procédural, vous pourriez vouloir faire toutes sortes de choses dans cette méthode un jour. 05 déc.. 132013-12-05 15:32:30

  0

Pas de magie ici. Simple sucre syntaxique pour '@var = @var || SomeClass.new'. Il suffit de dérouler n'importe quel opérateur Ruby '.. =' si vous avez des difficultés à envelopper votre esprit (et cela n'a aucun rapport avec 'defined?' BTW). De toute façon, aucun rubisiste profane ne devrait utiliser 'defined? 28 août. 142014-08-28 14:42:49

  0

Si vous * travaillez * avec des booléens et souhaitez que la valeur par défaut soit true si la variable n'a pas été explicitement définie sur false, vous pouvez utiliser cette construction: 'var = (var ou var.nil?)' 19 sept.. 142014-09-19 19:20:59

  0

'|| =' ne fonctionnera pas pour le booléen 'false'. disons 'a = false'' a || = true' alors 'a == true' vous devez utiliser' défini? pour le cas booléen a' 03 déc.. 152015-12-03 11:49:39

  0

@ArnaudMeuret [Trier de, pas vraiment.] (http://stackoverflow.com/a/2505285/1863564) - alors qu'il peut ne pas sembler identique, il vaut la peine de lire les réponses sur cette question. 08 mars. 162016-03-08 19:42:38


5

Voici un code, rien de sorcier, mais il fonctionne 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 visualation dans cet exemple de jouet.

  0

Pourquoi le vote négatif? ... 17 avril. 122012-04-17 11:59:00

  0

Probablement parce que le 'nil? 'Est optionnel. 18 juin. 122012-06-18 16:15:07

+5

@James: vraiment? Downvote au lieu de modifier et modifier? .... meh, tant pis.^_ ~ 20 juin. 122012-06-20 08:12:03


67

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 

substituant (var) avec votre variable. Cette syntaxe renverra une valeur true/false pour l'évaluation dans l'instruction if.

+11

Ce n'est pas nécessaire que nul la valeur false lorsqu'il est utilisé dans un test 05 avril. 122012-04-05 14:23:01

  0

Pourquoi ne pas 'défini? (Var) == nil'? 23 avril. 132013-04-23 22:17:43

  0

@ vol7ron - C'est une syntaxe parfaitement valide. Utiliser l'appel de '.nil?' Est plus idiomatique, comme on dit. Il est plus "orienté objet" de demander à un objet s'il est "nul" que d'utiliser un opérateur de comparaison. Ni l'un ni l'autre n'est difficile à lire, alors utilisez celui qui vous aide à expédier plus de produits. 26 oct.. 132013-10-26 13:05:42

  0

De quel énoncé parlez-vous?!? N'utilisez pas une réponse comme commentaire pour autre chose. 28 août. 142014-08-28 14:46:20


5

Vous pouvez essayer:

unless defined?(var) 
    #ruby code goes here 
end 
=> true 

Parce qu'il retourne un booléen.

  0

'SyntaxError: erreur de compilation (irb): 2: erreur de syntaxe, $ end inattendu, attendre kEND' 02 août. 122012-08-02 23:11:56

  0

pour utiliser une instruction' unless' semble trop compliqué 29 oct.. 122012-10-29 08:38:43


13

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 
  0

Qu'est-ce que cette réponse ajoute qui n'a pas été dit par les autres réponses ? 31 mai. 122012-05-31 22:54:23

+2

Il répond très bien à la question d'une manière plus utile, n'est-ce pas? 09 août. 122012-08-09 22:54:24

+2

Le guide de style rubis dit « Favor à moins que dans le cas des conditions négatives » https://github.com/bbatsov/ruby-style-guide 13 sept.. 132013-09-13 22:19:48


8

Utilisez defined? YourVariable
Keep it simple idiot ..;)

+7

Haha, idiot ... vous avez dit stupide 12 mai. 142014-05-12 19:19:02


2

S'il vous plaît noter la distinction entre "définie" 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 affecté!

  0

C'est quelque chose que je suis tombé. Je m'attendais à 'NameError Exception: variable locale non définie ou méthode', et était confus quand la seule affectation/mention de la variable était dans un bloc if qui n'était pas touché. 23 sept.. 152015-09-23 21:34:10


0

En outre, vous pouvez vérifier si elle est définie alors dans une chaîne par interpolation, si vous code:

puts "Is array1 defined and what type is it? #{defined?(@array1)}" 

Le système vous indiquera le type si elle est définie. S'il n'est pas défini, il retournera simplement un avertissement indiquant que la variable n'est pas initialisée.

Espérons que cela aide!:)


2

Comme beaucoup d'autres exemples montrent que vous n'avez pas réellement besoin d'un booléen d'une méthode pour faire des choix logiques dans ruby. 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 ne paie généralement pas 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ù il importe parce qu'elle repose sur la contrainte implicite de la valeur booléenne à sa représentation de chaîne.

>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}" 
var is defined? true vs local-variable 
=> nil 

3

Ceci est la réponse clé: le défini? méthode. La réponse acceptée ci-dessus illustre parfaitement cela.

Mais il y a un requin, qui se cache sous les vagues ...

Tenir compte de ce type de modèle rubis commun:

def method1 
    @x ||= method2 
end 

def method2 
    nil 
end 

Arrêtons et penser à ce sujet pendant une seconde. La méthode 2 renvoie toujours zéro. La première fois que vous appelez method1, la variable @x n'est pas définie. Par conséquent, la méthode 2 sera exécutée. et la méthode 2 mettra @x à zéro. C'est bien, et tout va bien. Mais que se passe-t-il la deuxième fois que vous appelez method1?

Rappelez-vous que @x a déjà été défini sur zéro. Mais la méthode 2 sera encore exécutée? Si la méthode 2 est une entreprise coûteuse, ce n'est peut-être pas ce que vous voulez.

Laisser le défini? méthode venir à la rescousse

def method1 
    return @x if defined? @x 
    @x = method2 
    end 

Si vous ne saviez pas ce truc, eh bien « vous allez besoin d'un plus gros bateau ».


2

Il convient de mentionner que l'utilisation defined pour vérifier si un champ spécifique est défini dans un hachage peut se comporter inattendu:

var = {} 
if defined? var['unknown'] 
    puts 'this is unexpected' 
end 
# will output "this is unexpected" 

La syntaxe est correcte, mais defined? var['unknown'] sera évalué à la chaîne "method", donc le bloc if sera exécuté

edit: la notation correcte pour vérifier si une clé existe dans un hachage serait:

if var.key?('unknown')