¿Por qué parece que Ruby eleva las declaraciones de variables desde el interior de una statement de caso, incluso si esa ruta de código no se ejecuta?

Definimos una función foo:

def foo(s) case s when'foo' x = 3 puts x.inspect when 'bar' y = 4 puts y.inspect end puts x.inspect puts y.inspect end 

Entonces lo llamamos de la siguiente manera:

 1.9.3p194 :017 > foo('foo') in foo scope 3 in outer scope 3 nil => nil 1.9.3p194 :018 > foo('bar') in bar scope 3 in outer scope nil 3 => nil 

¿Por qué la función no arroja un error sobre una variable local no registrada en ninguno de los casos? En el primer caso, la variable y parece que no debería existir, por lo que no puede invocar la inspect en el ámbito externo; lo mismo para x en el segundo caso.

Aquí hay otro ejemplo similar:

 def test1 x = 5 if false puts x.inspect end def test2 puts x.inspect end 

Y entonces:

 1.9.3p194 :028 > test1 nil => nil 1.9.3p194 :029 > test2 NameError: undefined local variable or method `x' for main:Object 

¿Que está pasando aqui? Parece que Ruby está elevando la statement de variables al scope externo, pero no sabía que esto es algo que hace Ruby. (La búsqueda de “elevación de Ruby” solo revela los resultados sobre el levantamiento de JavaScript).

Cuando el analizador de Ruby ve el identificador de secuencia, signo igual, valor, como en esta expresión

 x = 1 

asigna espacio para una variable local llamada x . La creación de la variable -no la asignación de un valor, sino la creación interna de una variable- siempre tiene lugar como resultado de este tipo de expresión, incluso si el código no se ejecuta. Considera este ejemplo:

 if false x = 1 end px # Output: nil py # Fatal Error: y is unknown 

La asignación a x no se ejecuta porque está envuelta en una prueba condicional fallida. Pero el analizador de Ruby ve la secuencia x = 1 , de la cual deduce que el progtwig involucra una variable local x . Al analizador no le importa si alguna vez se le asignó un valor a x. Su trabajo es solo buscar el código de las variables locales para las cuales se debe asignar el espacio. El resultado es que x habita un extraño tipo de limbo variable. Ha sido creado e inicializado a nil . En ese sentido, difiere de una variable que no tiene existencia en absoluto; como puede ver en el ejemplo, examinar x le da el valor nil , mientras que tratar de inspeccionar la variable no existente y resulta en un error fatal. Pero aunque x existe, no ha jugado ningún papel en el progtwig. Existe solo como un artefacto del proceso de análisis sintáctico.

Rubyist bien fundamentado, capítulo 6.1.2

El analizador de Ruby recorre todas las líneas y establece en cero todas las variable = . El código que se está ejecutando o no realmente no importa.

Consulte ¿Por qué puedo hacer referencia a una variable fuera de una statement if / unless / case que nunca se ejecutó?