Pregunta No entiendo el alcance local de ruby


En este ejemplo,

def foo(x)
  if(x > 5)
    bar = 100
  end
  puts bar
end

Entonces foo (6) Salidas: 100 y foo (3) no produce nada.

Sin embargo, si cambié la definición a

def foo(x)
  if(x > 5)
    bar = 100
  end
  puts bob
end

Aparece un error de "variable o método local indefinido".

¿Entonces mi pregunta es por qué no recibo este error cuando llamo a foo (3) y la barra nunca está configurada?


48
2017-11-11 13:26


origen


Respuestas:


Hay un par de cosas pasando aquí. Primero, las variables declaradas dentro del if bloque tienen el mismo alcance local que las variables declaradas en el nivel superior del método, que es por qué bar está disponible fuera del if. En segundo lugar, está recibiendo ese error porque bob está siendo referencia directamente de la nada. El intérprete de Ruby nunca lo ha visto y nunca lo ha visto inicializado. Sin embargo, se ha visto bar inicializado antes, dentro de la declaración if. Entonces cuando se pone en la barra, sabe que existe. Combina esos dos y esa es tu respuesta.


53
2017-11-11 13:47



Su segundo ejemplo es en realidad una pista falsa: el motivo por el que recibe una excepción no es porque bob no está inicializado, es porque es ambiguo. Es imposible decir si es una variable o un método.

Su primer ejemplo funciona, porque las variables locales no inicializadas (así como las variables globales y las variables de instancia) evalúan nil. Por lo tanto, puts bar está perfectamente bien: en un caso bar se inicializa a 100 y esto evalúa 100, en el otro caso no está inicializado y, por lo tanto, se evalúa como nil. puts llamadas to_s en su argumento, que se define para nil (simplemente devuelve la cadena vacía), así que todo está bien y elegante.

Ver también En Ruby, ¿por qué después de comenzar irb, foo.nil? dice error indefinido, y @ foo.nil? da "verdadero", y @@ wah.nil? da error de nuevo?


14
2017-11-11 15:54



Por lo tanto, no tome esto como un evangelio (ya que se basa más en la observación que en la comprensión), pero parece que el intérprete de rubíes señalará cualquier palabra (sin un símbolo delante) a la izquierda de un signo igual como local . Tu ejemplo es extraño, esto es aún más extraño

def foo
  bar = bar
  puts bar // nil, which gets coerced into ""
end

No entiendo por qué o cómo funciona, pero ahí lo tienes.


3
2017-11-11 13:41



foo(3) no produce nada Muestra una nueva línea.

Utilizando inspect te daría más de una pista:

def foo(x)
  if(x > 5)
    bar = 100
  end
  puts bar.inspect
end

foo(3)

imprime

nil

bar es una variable completamente desarrollada, que simplemente tiene un valor de nil.


2
2018-03-27 01:15



No estoy seguro de lo que estás preguntando. Corriendo foo(3) con la segunda definición siempre dará un error, ya que bob nunca está definido. El argumento para el método no cambia eso.


0
2017-11-11 13:38