Come posso verificare se una variabile è definita in Ruby? È disponibile un isset
metodo di tipo?
Come posso verificare se una variabile è definita in Ruby? È disponibile un isset
metodo di tipo?
Risposte:
Usa la defined?
parola chiave ( documentazione ). Restituirà una stringa con il tipo di elemento, o nil
se non esiste.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
Come ha commentato skalee: "Vale la pena notare che la variabile impostata su zero è inizializzata".
>> n = nil
>> defined? n
=> "local-variable"
||=
operatore) di seguito.
defined?
restituisce comunque vero per una variabile definita all'interno di quel blocco!
defined?
che ritorna booleano?
!!defined?(object_name)
Questo è utile se non vuoi fare nulla se esiste ma crealo se non esiste.
def get_var
@var ||= SomeClass.new()
end
Questo crea la nuova istanza solo una volta. Dopodiché continua a restituire il var.
||=
valori booleani, per non sentire il dolore della confusione.
nil
a meno che tu non voglia davvero valutare l'espressione ogni volta che viene chiamato quando ritornanil
var = (var or var.nil?)
La sintassi corretta per l'istruzione precedente è:
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
sostituendo ( var
) con la tua variabile. Questa sintassi restituirà un valore vero / falso per la valutazione nell'istruzione if.
defined?(var) == nil
?
.nil?
è più idiomatico, come si suol dire. È più "orientato agli oggetti" chiedere a un oggetto se non nil
usare un operatore di confronto. Nessuno dei due è difficile da leggere, quindi usa quello che ti aiuta a spedire più prodotti.
defined?(your_var)
funzionerà. A seconda di cosa stai facendo, puoi anche fare qualcosa del genereyour_var.nil?
your_var.nil?
perché restituisce vero falso ed è molto più bello da leggere e da scrivere di defined? var
. Grazie per questo.
your_var.nil?
comporterà un errore: undefined local variable or method your_var
quando non definito prima ...
Prova "a meno" invece di "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
Ecco del codice, niente scienza missilistica ma funziona abbastanza bene
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
Chiaramente, il codice da colorare non è necessario, solo una bella visualizzazione in questo esempio di giocattolo.
nil?
è facoltativo.
Questa è la risposta chiave: il defined?
metodo. La risposta accettata sopra illustra questo perfettamente.
Ma c'è uno squalo, in agguato sotto le onde ...
Considera questo tipo di modello rubino comune:
def method1
@x ||= method2
end
def method2
nil
end
method2
ritorna sempre nil
. La prima volta che chiami method1
, la @x
variabile non è impostata, quindi method2
verrà eseguita. e method2
verrà impostato @x
su nil
. Va bene, e tutto bene e bene. Ma cosa succede la seconda volta che chiami method1
?
Ricorda che @x è già stato impostato su zero. But method2
sarà ancora eseguito di nuovo !! Se method2 è un'impresa costosa, potrebbe non essere qualcosa che desideri.
Lascia che il defined?
metodo venga in soccorso - con questa soluzione, viene gestito quel caso particolare - utilizza quanto segue:
def method1
return @x if defined? @x
@x = method2
end
Il diavolo è nei dettagli: ma puoi eludere lo squalo in agguato con il defined?
metodo.
Puoi provare:
unless defined?(var)
#ruby code goes here
end
=> true
Perché restituisce un valore booleano.
SyntaxError: compile error (irb):2: syntax error, unexpected $end, expecting kEND
unless
un'affermazione sembra eccessivamente complicato
Come molti altri esempi mostrano che in realtà non è necessario un valore booleano da un metodo per effettuare scelte logiche in ruby. Sarebbe una forma scadente costringere tutto a un valore booleano a meno che tu non abbia effettivamente bisogno di un booleano.
Ma se hai assolutamente bisogno di un booleano. Uso !! (bang bang) o "falsy falsy rivela la verità".
› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Perché di solito non paga per forzare:
>> (!!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
Ecco un esempio in cui è importante perché si basa sulla coercizione implicita del valore booleano sulla sua rappresentazione di stringa.
>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil
Va notato che l'utilizzo defined
per verificare se un campo specifico è impostato in un hash potrebbe comportarsi in modo imprevisto:
var = {}
if defined? var['unknown']
puts 'this is unexpected'
end
# will output "this is unexpected"
La sintassi è corretta qui, ma defined? var['unknown']
verrà valutata sulla stringa "method"
, quindi ilif
blocco verrà eseguito
modifica: la notazione corretta per verificare se esiste una chiave in un hash sarebbe:
if var.key?('unknown')
Si noti la distinzione tra "definito" e "assegnato".
$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"
x è definito anche se non è mai assegnato!
NameError Exception: undefined local variable or method
ed ero confuso quando l'unica assegnazione / menzione della variabile era in un blocco if che non veniva colpito.
Inoltre, puoi verificare se è definito mentre sei in una stringa tramite interpolazione, se codifichi:
puts "Is array1 defined and what type is it? #{defined?(@array1)}"
Il sistema ti dirà il tipo se è definito. Se non è definito, restituirà solo un avviso indicante che la variabile non è inizializzata.
Spero che sia di aiuto! :)
defined?
è fantastico, ma se ti trovi in un ambiente Rails puoi anche usarlo try
, specialmente nei casi in cui desideri controllare un nome di variabile dinamico:
foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo) # => 1
try(:bar) # => nil
try(my_foo) # => 1
try(my_bar) # => nil
nil
è inizializzata.