Wie kann ich überprüfen, ob eine Variable in Ruby definiert ist? Gibt es eine isset
- Methode?
Verwenden Sie das Schlüsselwort defined?
( documentation ). Es wird eine Zeichenfolge mit der Art des Elements oder nil
zurückgegeben, wenn es nicht vorhanden ist.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
Skalee kommentierte: "Es ist zu beachten, dass die Variable, die auf Null gesetzt ist, initialisiert wird."
>> n = nil
>> defined? n
=> "local-variable"
Dies ist nützlich, wenn Sie nichts tun möchten, wenn es existiert, aber es erstellen, wenn es nicht existiert.
def get_var
@var ||= SomeClass.new()
end
Dadurch wird die neue Instanz nur einmal erstellt. Danach kehrt der var immer wieder zurück.
Die korrekte Syntax für die obige Anweisung lautet:
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
ersetzen Sie (var
) durch Ihre Variable. Diese Syntax gibt einen Wahr/Falsch-Wert zur Auswertung in der if-Anweisung zurück.
defined?(your_var)
wird funktionieren. Je nachdem, was Sie tun, können Sie auch etwas wie your_var.nil?
tun.
Versuchen Sie "außer" anstelle von "wenn"
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
Verwenden Sie defined? YourVariable
Halten Sie es einfach dumm ..;)
Hier ist etwas Code, nichts Raketenwissenschaft, 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
Natürlich ist der Farbcode nicht notwendig, nur eine schöne Visualisierung in diesem Spielzeugbeispiel.
Dies ist die Schlüsselantwort: die defined?
-Methode. Die akzeptierte Antwort oben veranschaulicht dies perfekt.
Aber unter den Wellen lauert ein Hai ...
Betrachten Sie diese Art von allgemeinem Ruby-Muster:
def method1
@x ||= method2
end
def method2
nil
end
method2
gibt immer nil
zurück. Wenn Sie method1
zum ersten Mal aufrufen, wird die Variable @x
nicht festgelegt. Daher wird method2
ausgeführt. und method2
setzen @x
auf nil
. 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. But method2
wird immer noch ausgeführt !! Wenn method2 ein kostspieliges Unterfangen ist, ist dies möglicherweise nicht das, was Sie wollen.
Lassen Sie die defined?
-Methode zur Rettung kommen - bei dieser Lösung wird dieser bestimmte Fall behandelt - verwenden Sie Folgendes:
def method1
return @x if defined? @x
@x = method2
end
Der Teufel steckt im Detail: Sie können diesen lauernden Hai jedoch mit der defined?
-Methode umgehen.
Du kannst es versuchen:
unless defined?(var)
#Ruby code goes here
end
=> true
Weil es einen Boolean zurückgibt.
Wie viele andere Beispiele zeigen, benötigen Sie für eine logische Auswahl in Ruby nicht wirklich einen booleschen Wert. Es wäre eine schlechte Form, alles zu einem Boolean zu zwingen, es sei denn, Sie benötigen tatsächlich einen Boolean.
Aber wenn Sie unbedingt einen Boolean brauchen. Benutzen !! (Bang Bang) oder "Falsches Falsches enthüllt die Wahrheit".
› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Warum lohnt es sich normalerweise nicht 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, in dem es wichtig ist, weil es auf den impliziten Zwang des booleschen Werts in seine Zeichenfolgendarstellung angewiesen ist.
>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil
Es sollte erwähnt werden, dass die Verwendung von defined
zur Überprüfung, ob ein bestimmtes Feld in einem Hash gesetzt ist, möglicherweise unerwartet verhält:
var = {}
if defined? var['unknown']
puts 'this is unexpected'
end
# will output "this is unexpected"
Die Syntax ist hier korrekt, aber defined? var['unknown']
wird in der Zeichenfolge "method"
ausgewertet, sodass der if
-Block ausgeführt wird
edit: Die korrekte Notation zur Überprüfung, ob ein Schlüssel in einem Hash existiert, wäre:
if var.key?('unknown')
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 niemals zugewiesen ist!
defined?
ist großartig. Wenn Sie sich jedoch in einer Rails-Umgebung befinden, können Sie auch try
verwenden, insbesondere wenn Sie den Namen einer dynamischen Variablen überprüfen möchten:
foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo) # => 1
try(:bar) # => nil
try(my_foo) # => 1
try(my_bar) # => nil
Außerdem können Sie durch Interpolation überprüfen, ob es in einem String definiert ist, wenn Sie Folgendes codieren:
puts "Is array1 defined and what type is it? #{defined?(@array1)}"
Das System teilt Ihnen den Typ mit, falls es definiert ist .. Wenn es nicht definiert ist, wird nur eine Warnung ausgegeben, dass die Variable nicht initialisiert ist.
Hoffe das hilft! :)