2008-11-13 15 views

Antwort

719

Verwenden Sie das Schlüsselwort defined? (documentation). Es wird ein String mit der Art des Elements zurückgegeben, oder nil, wenn es nicht existiert.

>> a = 1 
=> 1 
>> defined? a 
=> "local-variable" 
>> defined? b 
=> nil 
>> defined? nil 
=> "nil" 
>> defined? String 
=> "constant" 
>> defined? 1 
=> "expression" 

Wie skalee kommentierte: „Es ist erwähnenswert, dass Variable, die auf Null gesetzt wird initialisiert.“

+82

Es ist erwähnenswert, dass Variable, die auf' nil' * gesetzt ist * initialisiert ist. – skalee

+7

Wenn Sie eine Variable setzen möchten, wenn sie nicht existiert, und sie in Ruhe lassen, finden Sie unter @ danmayers Antwort (mit dem Operator || = ') weiter unten. – jrdioko

+2

Das ist so radikal. – Ziggy

18

defined?(your_var) arbeiten. Je nachdem, was Sie gerade tun, können Sie auch etwas wie your_var.nil?

+0

+1 für 'your_var.nil?', Weil es wahr von false zurückgibt und viel besser zu lesen und zu schreiben ist als 'definiert? var'. Danke dafür. – kakubei

+25

'your_var.nil?' Führt zu einem Fehler: 'undefined lokale Variable oder Methode your_var', wenn nicht vorher definiert ... – Gobol

87

Dies ist nützlich, wenn Sie nichts tun wollen, wenn es existiert, aber erstellen Sie es, wenn es nicht existiert.

def get_var 
    @var ||= SomeClass.new() 
end 

Dies erstellt nur einmal die neue Instanz. Danach gibt es nur die Var zurück.

+7

Dies ist übrigens sehr idiomatisch Ruby und sehr typisch. – jrdioko

+0

Danke für diesen Eingang! Ich bin ein Ruby/Rails Anfänger und kam gestern Abend über diese Syntax, hatte eine harte Zeit herauszufinden, was es bedeutete. Sieht sehr praktisch aus! –

+0

das funktioniert nicht für die Definition von Konstanten –

5

Hier ist ein Code, nichts Wissenschaft Rakete aber es funktioniert gut genug

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 

klar, dass die Färbung Code nicht notwendig ist, nur eine nette visualation in diesem Spielzeug Beispiel.

+0

Warum die down vote? ... – Sardathrion

+0

Vermutlich weil das 'nil?' Optional ist. – James

+5

@James: wirklich? Downvote statt bearbeiten und ändern? .... meh, egal.^_ ~ – Sardathrion

67

Die korrekte Syntax für die obige Aussage ist:

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 

(var) mit Variable ersetzt wird. Diese Syntax gibt einen Wahr/Falsch-Wert für die Auswertung in der if-Anweisung zurück.

+11

Das ist nicht notwendig, da nil bei Verwendung in einem Test zu false führt – Jerome

+0

Warum nicht definiert? (Var) == nil? – vol7ron

+0

@ vol7ron - Das ist absolut gültige Syntax. Der Aufruf von '.nil? 'Ist idiomatischer, wie man sagt. Es ist eher "objektorientiert", ein Objekt zu fragen, wenn es "nicht" ist, als einen Vergleichsoperator zu verwenden. Keiner ist schwer zu lesen, also verwenden Sie den, der Ihnen hilft, mehr Produkt zu versenden. – juanpaco

5

können Sie versuchen:

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

Weil es einen Booleschen Wert zurück.

+0

'SyntaxError: Fehler bei der Kompilierung (irb): 2: Syntaxfehler, unerwartete $ end, erwartet kEND' –

+0

zu verwenden eine 'außer' Anweisung scheint übermäßig kompliziert – johannes

13

Try "es sei denn" anstelle von "if"

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

Was fügt diese Antwort hinzu, die nicht von den anderen Antworten gesagt wurde ? –

+2

Es beantwortet sehr schön die Frage in einer nützlicheren Weise, nicht wahr? – look

+2

Der Rubin-Stil Guide sagt "Gunst, wenn nicht vorbei, wenn für negative Bedingungen" https://github.com/bbatsov/ruby-style-guide – ChrisPhoenix

8

Verwenden defined? YourVariable
Halten Sie es einfach dumm ..;)

+7

Haha, albern ... Sie sagten albern – Relic

2

Bitte beachten Sie die Unterscheidung zwischen "definiert" und " zugewiesen ".

$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f' 
nil 
"local-variable" 

x ist definiert, obwohl es nie zugewiesen wurde!

+0

Dies ist etwas, das ich gerade gestoßen bin. Ich erwartete 'NameError Exception: undefinierte lokale Variable oder Methode' und war verwirrt, als die einzige Zuweisung/Erwähnung der Variablen in einem if-Block war, der nicht getroffen wurde. –

0

Außerdem können Sie überprüfen, ob es während durch Interpolation in einem String definiert ist, wenn Sie den Code ein:

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

Das System wird Ihnen sagen, die Art, wenn sie definiert ist. Wenn es nicht definiert ist, wird nur eine Warnung zurückgegeben, die besagt, dass die Variable nicht initialisiert wurde.

Hoffe, das hilft!:)

2

Wie viele andere Beispiele zeigen, benötigen Sie nicht wirklich einen Boolean von einer Methode, um logische Entscheidungen in Ruby zu treffen. Es wäre eine schlechte Form, alles zu einem booleschen Wert zu zwingen, es sei denn, du benötigst tatsächlich einen booleschen Wert.

Aber wenn Sie unbedingt einen Boolean benötigen. Benutzen !! (bang bang) oder "falsy falsy enthüllt die Wahrheit".

› irb 
>> a = nil 
=> nil 
>> defined?(a) 
=> "local-variable" 
>> defined?(b) 
=> nil 
>> !!defined?(a) 
=> true 
>> !!defined?(b) 
=> false 

Warum es normalerweise nicht bezahlen zu zwingen:

>> (!!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 

Hier ist ein Beispiel, wo es darauf ankommt, weil es auf dem impliziten Zwang des Booleschen Wertes in seine String-Darstellung beruht.

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

Dies ist die Schlüsselantwort: die definierte? Methode. Die oben angenommene Antwort zeigt dies perfekt.

Aber es ist ein Hai, unter den Wellen lauern ...

diese Art von gemeinsamen Rubin Muster vor:

def method1 
    @x ||= method2 
end 

def method2 
    nil 
end 

Lassen Sie uns über diese für eine Sekunde innehalten und nachdenken. Methode 2 gibt immer nil zurück. Wenn Sie method1 zum ersten Mal aufrufen, wird die Variable @x nicht gesetzt - daher wird method2 ausgeführt. und Methode 2 setzt @x auf Null. Das ist gut und alles gut und gut. Aber was passiert beim zweiten Aufruf von method1?

Denken Sie daran, dass @x bereits auf Null gesetzt wurde. Aber Methode 2 wird noch einmal ausgeführt? Wenn Methode2 ein kostspieliges Unterfangen ist, ist dies möglicherweise nicht das, was Sie wollen.

Lassen Sie das definiert? Verfahren zur Rettung kamen

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

Wenn Sie nicht über diesen Trick nicht kannten, und dann „du wird ein größeres Boot brauchen“.

2

Es sollte erwähnt werden, dass defined Verwendung zu überprüfen, ob ein bestimmtes Feld in einem Hash gesetzt wird, könnte sich verhalten unerwartet:

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

Die Syntax hier richtig ist, aber defined? var['unknown'] wird auf den String "method", so ausgewertet werden die korrekte Bezeichnung für die Überprüfung, ob ein Schlüssel vorhanden ist in einem Hash wäre: der if Block

bearbeiten ausgeführt werden

if var.key?('unknown') 
Verwandte Themen