2008-11-13 30 views

Respuesta

719

Utilice la palabra clave defined? (documentation). Devolverá una Cadena con el tipo de artículo, o nil si no existe.

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

As skalee ha comentado: "Vale la pena señalar que la variable que se establece en nil se inicializa."

>> n = nil 
>> defined? n 
=> "local-variable" 
+82

Vale la pena señalar que la variable que está configurada en' nil' * está * inicializada. – skalee

+7

Si desea establecer una variable si no existe y dejarla en paz, si lo hace, consulte la respuesta de @ danmayer (que implica el operador '|| =') a continuación. – jrdioko

+2

Eso es tan radical. – Ziggy

18

defined?(your_var) funcionará. Dependiendo de lo que esté haciendo, también puede hacer algo como your_var.nil?

+0

+1 para 'your_var.nil?' Porque devuelve verdadero de falso y es mucho mejor para leer y escribir que 'definido? var'. Gracias por esto. – kakubei

+25

'your_var.nil?' Dará como resultado un error: 'variable local indefinida o método your_var' cuando no se definió antes ... – Gobol

87

Esto es útil si usted quiere hacer nada si no existe, pero crearlo si no existe.

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

Esto solo crea la nueva instancia una vez. Después de eso, solo sigue devolviendo la var.

+7

Esto es muy idiomático Ruby y muy típico, por cierto. – jrdioko

+0

¡Gracias por esta entrada! Soy un principiante de ruby ​​/ rails y me encontré con esta sintaxis ayer por la noche, me costó entender lo que significaba. ¡Parece muy útil! –

+0

esto no funcionará para definir las constantes –

5

Aquí hay un código, nada ciencia de cohetes pero funciona bastante 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 coloración no es necesario, sólo un bonito visualation en este ejemplo de juguete.

+0

¿Por qué el voto hacia abajo? ... – Sardathrion

+0

Probablemente porque el 'nil?' Es opcional. – James

+5

@James: ¿en serio? ¿Vota menos en vez de editar y cambiar? ... meh, no importa.^_ ~ – Sardathrion

67

La sintaxis correcta para la instrucció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 la variable. Esta sintaxis devolverá un valor verdadero/falso para la evaluación en la sentencia if.

+11

Eso no es necesario ya que nil se evalúa como falso cuando se usa en una prueba – Jerome

+0

¿Por qué no 'defined? (Var) == nil'? – vol7ron

+0

@ vol7ron - Esa es la sintaxis perfectamente válida. Usar la llamada a '.nil?' Es más idiomático, como dicen. Es más "orientado a objetos" preguntar a un objeto si es 'nil' que usar un operador de comparación. Ninguno es difícil de leer, así que use el que le ayude a enviar más producto. – juanpaco

5

Usted puede tratar de:

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

porque devuelve un valor lógico.

+0

'SyntaxError: error de compilación (irb): 2: error de sintaxis, inesperado $ end, esperando que'END 'de kEND' –

+0

parezca demasiado complicado – johannes

13

Try "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 
+0

¿Qué agrega esta respuesta que no ha sido dicha por las otras respuestas? ? –

+2

Responde muy bien la pregunta de una forma más útil, ¿no? – look

+2

La guía de estilo de rubí dice "Favor a menos que exista si las condiciones son negativas" https://github.com/bbatsov/ruby-style-guide – ChrisPhoenix

8

Uso defined? YourVariable
Debe ser sencillo tonta ..;)

+7

Jaja, tonto ... dijiste tonto – Relic

2

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 a pesar de que nunca se asigna!

+0

Esto es algo que acabo de encontrar. Esperaba 'NameError Exception: variable o método local indefinido', y me confundí cuando la única asignación/mención de la variable estaba en un bloque if que no recibía ningún golpe. –

0

Además, se puede comprobar si está definida, mientras que en una cadena a través de la interpolación, si el código:

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

El sistema le dirá el tipo si está definida. Si no está definido, devolverá una advertencia diciendo que la variable no se ha inicializado.

Espero que esto ayude!:)

2

Como muchos otros ejemplos muestran que en realidad no necesita un booleano de un método para realizar elecciones lógicas en ruby. Sería una forma pobre forzar todo a un booleano a menos que realmente necesite un booleano.

Pero si necesitas absolutamente un booleano. Utilizar !! (bang bang) o "falsy falsy 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 para 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 

He aquí un ejemplo donde importa porque se basa en la coerción implícita del valor booleano la representación de cadena.

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

Esta es la respuesta clave: la definida? método. La respuesta aceptada arriba ilustra esto perfectamente.

Pero hay un tiburón, al acecho debajo de las olas ...

consideran este tipo de patrón de rubí común:

def method1 
    @x ||= method2 
end 

def method2 
    nil 
end 

Vamos a parar y pensar en esto por un segundo. el método 2 siempre devuelve nil. La primera vez que llama al método 1, la variable @x no está configurada; por lo tanto, se ejecutará el método2. y el método 2 establecerá @x a nil. Eso está bien, y todo está bien. Pero, ¿qué ocurre la segunda vez que llamas a method1?

Remember @x ya se ha establecido en nil. Pero el método 2 todavía se ejecutará de nuevo? Si method2 es una empresa costosa, esto podría no ser algo que desee.

Deje lo definido? Método venir al rescate

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

Si usted no sabía sobre ese truco, bueno, entonces "Vas a necesitar un barco más grande".

2

Cabe mencionar que el uso de defined para comprobar si un campo específico se encuentra en un hash podría comportarse 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á a la cadena "method", por lo el bloque if se ejecutará

edición: la notación correcta para comprobar si existe una clave en un hash sería:

if var.key?('unknown') 
Cuestiones relacionadas