2012-02-02 13 views
5

Duplicar posible:
Why a = a is nil in Ruby?¿Por qué puedo asignarle una variable indefinida en Ruby y obtener nil?

Hay una, digamos, "extraño fenómeno" en Ruby con el uso de variables no definidas. Es como esto:

# irb session follows 
# 
foo  # undefined local variable or method 'foo' 
bar  # same for 'bar' 
foo = bar # still same for 'bar' 
foo = foo # nil - HUH? 
foo  # is now set to nil!? 

qué puedo asignar una variable no definida a sí mismo en Ruby y obtener nil?

Tenga en cuenta que estoy usando Ruby 1.9.3 aquí. No estoy seguro de qué otras versiones esto puede ser cierto en.

(Gracias a Gary Bernhardt para demostrar esto en su hilarious talk.)

+1

Presumiblemente, 'foo = foo' se evalúa en dos pasos. El primero "declara" la variable con un valor predeterminado, y el segundo se lo asigna a sí mismo. – millimoose

Respuesta

2

Ninguna magia en Rubí, debido a la idea de que todo es un objeto . En realidad, hay un objeto nulo único que se asigna. Cuando lo hizo

foo = bar 

la variable "foo" saltó a la existencia y tomó como valor el objeto mágico nulo. Antes de realizar la tarea, Ruby no tenía forma de "saber" qué es foo (¿es una variable ?, ¿una llamada a un método?), Pero una vez que haces la tarea, comienza a tratarla como una variable.

+0

Bueno, 'foo = foo' también funciona sin ninguna declaración previa. –

+0

Seguro, y por la misma razón. Lo nil no es la cosa, es solo un marcador de posición para un valor indefinido. La cosa es la asignación, una vez que Ruby ve la asignación, "decide" tratar la ficha a la izquierda de "=" como una variable. – theglauber

+1

@theglauber, Eso no explica "foo = foo". En el caso de 'foo = bar' si tanto foo como la barra no están definidos, aún se genera una excepción. El extraño caso del funcionamiento de 'foo = foo' se debe al hecho de que el intérprete de ruby ​​realiza la inicialización antes de la evaluación de la expresión. Esencialmente en la mano izquierda, foo está en nada; luego, cuando el intérprete alcanza la evaluación de la expresión para realizar la tarea, el foo del lado derecho ya se ha inicializado. – bigtunacan

7

El hecho de que la barra no está definido, no es en realidad la parte más interesante, ya que la asignación no necesita ni siquiera ser tratado, por ejemplo

if false 
    foo = 1 
end 

Conjuntos foo a cero. Según lo entiendo, el alcance de la variable local se determina estáticamente en el sentido de que se determina sin ejecutar realmente el código, simplemente analizándolo. Ruby piensa que la tarea podría suceder, por lo que crea la variable local y la establece en cero. Ver http://ruby.runpaint.org/variables#local

+0

Mejor aún, la variable a asignar en la sentencia if no tiene que definirse: 'foo = wat if false' –

Cuestiones relacionadas