Duda sobre eval()

Hola,

tengo una duda sobre eval() a partir de este trozo de código

what = 'photo'

@files.each do |f|

  # Método 1
  #p = eval("p = #{what.capitalize}.new")

  # Método 2
  #p = eval("#{what.capitalize}.new")

  # Método 3
  #eval("p = #{what.capitalize}.new")

  p.title = f
  p.uploaded_data = uploaded_file(path+f, content_type, f)
  @promotion.send(w2) << p
end

Los métodos 1 y 2 para crear p mediante eval() funcionan en cualquier
situación. El método 3 en cambio no funciona en la aplicación (“p”
queda como nil y da error en la línea de title= ) y en cambio, de
forma desconcertante, sí funciona tanto en irb como al hacer un
breakpoint.

¿Se trata de algún error en alguna otra parte del código o es un
comportamiento esperable?

Muchas gracias.


Manuel, que
piensa que eres una excelente persona y medra en torno a
http://simplelogica.net y/o simplelogica.net
Recuerda comer mucha fruta y verdura.

On 8/21/07, Manuel González Noriega [email protected]
wrote:

  #p = eval("p = #{what.capitalize}.new")
end

comportamiento esperable?
Hola Manuel,

Creo que es un problema de alcance de la variable.

¿Qué pasa si agregas esta línea antes del #each?

p = nil

@files.each do |f|

Al margen: quizás podrías lograr lo mismo sin el bello #eval

p = Module.const_get(what.capitalize).new

¿Sirve?

Saludos!

On 21/08/07, Damian J. [email protected] wrote:

Creo que es un problema de alcance de la variable.

¿Qué pasa si agregas esta línea antes del #each?

p = nil

Pues sí, funciona, aunque ahora mismo confieso que no veo el porqué :slight_smile:

Al margen: quizás podrías lograr lo mismo sin el bello #eval

p = Module.const_get(what.capitalize).new

Ah, buen. Lo apunto

Gracias por la ayuda y el consejo, Damian :slight_smile:


Manuel, que
piensa que eres una excelente persona y medra en torno a
http://simplelogica.net y/o http://simplelogica.net/logicola/
Recuerda comer mucha fruta y verdura.

Hola Manuel,

Un caso interesante, buscando un poco he encontrado este mensaje:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/144006

“Short story: Ruby determines local variables at parse time”, de modo
que declarar variables dentro de eval no parece recomendable :wink:

Saludos,
Raul M.

On 8/21/07, Manuel González Noriega [email protected]
wrote:

On 21/08/07, Damian J. [email protected] wrote:

Creo que es un problema de alcance de la variable.

¿Qué pasa si agregas esta línea antes del #each?

p = nil

Pues sí, funciona, aunque ahora mismo confieso que no veo el porqué :slight_smile:

Parece que tiene que ver con el hecho de que Ruby necesita “ver” el
nombre de la variable antes de la primera llamada para determinar el
alcance. Por ejemplo:

5.times do |i|
n = i
end
puts n

Tira un “NameError: undefined local variable or method `n’ for
main:Object”

En cambio:

if false
n = “Hola”
end

5.times do |i|
n = i
end
puts n

Funciona, porque como te dice Raúl, Ruby determina las variables
locales en tiempo de parseo, así que no importa que esa
asignaciónnunca se ejecuta (if false), el intérprete “ya vio” que hay una
variable local externa al bloque.

En cuanto al eval, quizás podría ser equiparable a:

p = nil
Proc.new { p += 1 }.call
Proc.new { p += 1 }.call
Proc.new { p += 1 }.call

Sin la primera línea, no funciona. Quizás el eval está creando un
scope como cada uno de estos Procs…

Qué delirio :slight_smile:

Saludos!