2011-08-07 13 views
6

Estoy ejecutando ruby ​​1.9.2p180 (2011-02-18 revisión 30909) [x86_64-linux].en ruby, ¿por qué no está definido? trabajo como uno esperaría cuando se utiliza con asegurar

#!/usr/bin/env ruby 

    def ouch() 
      raise ArgumentError, "woof" 
      fred = 3 
      return(nil) 

    ensure 
      if (defined?(fred)) then 
        printf("fred is defined (%s)\n", fred.inspect()) 
      else 
        printf("fred is not defined\n") 
      end 

    end # ouch() 


    ouch() 

Cuando se ejecuta, la salida del script rubí anterior es bastante inesperado.

$ ./ouch.rb 
    fred is defined (nil) 
    ./ouch.rb:4:in `ouch': woof (ArgumentError) 
      from ./ouch.rb:22:in `<main>' 

Así se produce el aumento/excepción, Fred no está recibiendo establece en 3, pero cada vez es más definido y ajustado a cero, anulando la comprobación de definido?(). Esto es muy confuso ¿Es esto un error? Obviamente, la prueba para la definición debe ser seguida por la prueba de nula.

Si esto no es un error, ¿alguien puede explicar por qué no?

Respuesta

7

Las variables locales en Ruby se definen entre la línea en la que se usan por primera vez y el final del alcance léxico actual. También se inicializaron implícitamente en nil.

Ten en cuenta también este ejemplo:

if false 
    var = 123 
end 
p var # => nil 

Este comportamiento está destinado. Ruby está diseñado de la manera en que podría diferenciar entre las llamadas al método y el acceso variable local en el paso parse, no en la ejecución. Por lo tanto, después del punto en el que se ha definido una variable, todas las referencias posteriores a ese nombre accederán a la variable, ya sea que se establezca explícitamente en algún valor o no.

(Si alguien me apuntará al tipo de llamada CALL_VCALL método en Ruby, contestaré que por lo que yo sé, sólo se utiliza en eval: cuando se está eval -ing, no se puede saber desde el principio si alguna variable se definió en la línea anterior del IRB, por lo tanto, los accesos a que se deben apresados ​​y enviados en consecuencia.)

+0

las variables de Ruby se definen a partir de la línea de código fuente que se les asigna en primer lugar. No puede usarlos antes de que sean asignados. Por lo tanto, no están "definidos" en la parte superior del bloque en el que se usan ". –

+0

@RobertKlemme Excelente punto, fijo. – whitequark

4
  • no un error
  • las variables locales son creados por asignación, pero resulta que la asignación sólo se necesita ser analizado, no ejecutado en realidad ...

Aquí es un ejemplo más simple:

if false 
    alocal = 123 
end 
p defined? alocal 
=> "local-variable" 
Cuestiones relacionadas