2008-11-13 10 views

Répondre

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. – skalee

+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. – jrdioko

+2

C'est tellement rad. – Ziggy

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. – kakubei

+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 ... – Gobol

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. – jrdioko

+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! –

+0

cela ne fonctionnera pas pour définir des constantes –

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? ... – Sardathrion

+0

Probablement parce que le 'nil? 'Est optionnel. – James

+5

@James: vraiment? Downvote au lieu de modifier et modifier? .... meh, tant pis.^_ ~ – Sardathrion

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 – Jerome

+0

Pourquoi ne pas 'défini? (Var) == nil'? – vol7ron

+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. – juanpaco

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' –

+0

pour utiliser une instruction' unless' semble trop compliqué – johannes

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 ? –

+2

Il répond très bien à la question d'une manière plus utile, n'est-ce pas? – look

+2

Le guide de style rubis dit « Favor à moins que dans le cas des conditions négatives » https://github.com/bbatsov/ruby-style-guide – ChrisPhoenix

8

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

+7

Haha, idiot ... vous avez dit stupide – Relic

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é. –

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') 
Questions connexes