¿Cómo puedo verificar si una variable está definida en Ruby? ¿Hay un isset
método de tipo disponible?
¿Cómo puedo verificar si una variable está definida en Ruby? ¿Hay un isset
método de tipo disponible?
Respuestas:
Use la defined?
palabra clave ( documentación ). Devolverá una Cadena con el tipo de elemento, o nil
si no existe.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
Como comentó skalee: "Vale la pena señalar que la variable que se establece en nulo se inicializa".
>> n = nil
>> defined? n
=> "local-variable"
||=
operador) a continuación.
defined?
aún se devuelve verdadero para una variable definida dentro de ese bloque!
defined?
ese devuelve boolean?
!!defined?(object_name)
Esto es útil si no desea hacer nada si existe, sino crearlo si no existe.
def get_var
@var ||= SomeClass.new()
end
Esto solo crea la nueva instancia una vez. Después de eso, simplemente sigue devolviendo la var.
||=
con valores booleanos, para que no sienta el dolor de la confusión.
nil
así a menos que realmente desea evaluar la expresión cada vez que se llama cuando se hace el retornonil
var = (var or var.nil?)
La sintaxis correcta para la declaración anterior es:
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
sustituyendo ( var
) con su variable. Esta sintaxis devolverá un valor verdadero / falso para la evaluación en la instrucción if.
defined?(var) == nil
?
.nil?
es más idiomático, como dicen. Es más "orientado a objetos" preguntarle a un objeto si es nil
que usar un operador de comparación. Ninguno de los dos es difícil de leer, así que use el que le ayude a enviar más productos.
defined?(your_var)
trabajará. Dependiendo de lo que estés haciendo, también puedes hacer algo comoyour_var.nil?
your_var.nil?
porque devuelve verdadero de falso y es mucho más agradable de leer y escribir que defined? var
. Gracias por esto.
your_var.nil?
producirá un error: undefined local variable or method your_var
cuando no se haya definido antes ...
Intente "a menos que" en lugar 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
Aquí hay un código, nada de ciencia espacial pero funciona lo suficientemente 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
Claramente, el código de color no es necesario, solo una buena visualización en este ejemplo de juguete.
nil?
es opcional.
Esta es la respuesta clave: el defined?
método. La respuesta aceptada arriba ilustra esto perfectamente.
Pero hay un tiburón al acecho debajo de las olas ...
Considere este tipo de patrón de rubí común:
def method1
@x ||= method2
end
def method2
nil
end
method2
siempre vuelve nil
. La primera vez que llama method1
, la @x
variable no está establecida, por method2
lo tanto , se ejecutará. y method2
se establecerá @x
en nil
. Eso está bien, y todo bien y bien. ¿Pero qué pasa la segunda vez que llamas method1
?
Recuerde que @x ya se ha establecido en nulo. But method2
todavía se ejecutará de nuevo !! Si method2 es una tarea costosa, esto podría no ser algo que desee.
Deje que el defined?
método salga al rescate - con esta solución, se maneja ese caso particular - use lo siguiente:
def method1
return @x if defined? @x
@x = method2
end
El diablo está en los detalles: pero puedes evadir a ese tiburón al acecho con el defined?
método.
Puedes probar:
unless defined?(var)
#ruby code goes here
end
=> true
Porque devuelve un valor booleano.
SyntaxError: compile error (irb):2: syntax error, unexpected $end, expecting kEND
unless
declaración parece demasiado complicado
Como muchos otros ejemplos muestran, en realidad no necesita un booleano de un método para tomar decisiones lógicas en ruby. Sería una forma deficiente obligar todo a un booleano a menos que realmente necesite un booleano.
Pero si absolutamente necesitas un booleano. Utilizar !! (bang bang) o "falso falso revela la verdad".
› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Por qué no suele pagar coaccionar:
>> (!!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
Aquí hay un ejemplo donde importa porque se basa en la coerción implícita del valor booleano a su representación de cadena.
>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil
Cabe mencionar que usar defined
para verificar si un campo específico está configurado en un hash podría comportarse de manera inesperada:
var = {}
if defined? var['unknown']
puts 'this is unexpected'
end
# will output "this is unexpected"
La sintaxis es correcta aquí, pero defined? var['unknown']
se evaluará en la cadena "method"
, por lo queif
que se ejecutará bloque
editar: La notación correcta para verificar si existe una clave en un hash sería:
if var.key?('unknown')
Tenga en cuenta la distinción entre "definido" y "asignado".
$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"
¡x se define aunque nunca se asigne!
NameError Exception: undefined local variable or method
, y estaba confundido cuando la única asignación / mención de la variable estaba en un bloque if que no estaba siendo golpeado.
Además, puede verificar si está definido mientras está en una cadena a través de la interpolación, si codifica:
puts "Is array1 defined and what type is it? #{defined?(@array1)}"
El sistema le dirá el tipo si está definido. Si no está definido, solo devolverá una advertencia diciendo que la variable no está inicializada.
¡Espero que esto ayude! :)
defined?
es genial, pero si está en un entorno Rails, también puede usarlo try
, especialmente en los casos en que desea verificar un nombre de variable dinámica:
foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo) # => 1
try(:bar) # => nil
try(my_foo) # => 1
try(my_bar) # => nil
nil
se inicializa.