From: "Ara.T.Howard" Date: 2005-06-02T23:28:58+09:00 Subject: how to create a variable with eval - solved! [WAS] Re: binding, ObjectSpace._id2ref [WAS] Re: [ANN] parseargs-0.0.0 On Thu, 2 Jun 2005, Zev Blut wrote: > Hello, > > On Thu, 02 Jun 2005 05:30:28 +0900, Ara.T.Howard > wrote: > >> the problem here is that the variables will only be __available__ through >> eval >> either. eg. you'd have to >> >> p 'eval a' >> >> and could never >> >> p a >> >> i seem to recall a way of working around this but can't remember the >> thread... >> if i can figure it out i'll add this feature. > Wow I am quite surprised at this! everyone is! ;-) > It is quite odd that adding a variable through the use of eval, makes the > variable appear in the local_variables method, but that you cannot access > the variable unless you use eval... Below is a simpler example showing how > using eval modifies the the local_variables response. > > ---------------------------------------------------------------------- > puts "[" + local_variables.join(" , ") + "]" > #=> [] > eval 'a = 42' > puts "[" + local_variables.join(" , ") + "]" > #=> [a] > puts a > #=> undefined local variable or method `a' for main:Object (NameError) > ---------------------------------------------------------------------- > > If you cannot access a in your binding, why would eval add a to the > local_variables? Can anyone explain this? I would like to know. i didn't know about that, but it suggests a way to rig method_missing in Object to make it __seem__ like a variable has been created in scope: for example: harp:~ > cat a.rb require 'binding_of_caller' class Object def create_var name, env = nil Binding::of_caller do |bnd| eval("#{ name }=nil", env || bnd) end end def set_var name, value, env = nil Binding::of_caller do |bnd| eval("#{ name }=ObjectSpace::_id2ref(#{ value.object_id })", env || bnd) end end def get_var name, env = nil Binding::of_caller do |bnd| eval("#{ name }", env || bnd) end end alias __method_missing__ method_missing def method_missing(m,*a,&b) Binding::of_caller do |bnd| lv = eval 'local_variables', bnd name = m.to_s if lv.include? name return(get_var(name, bnd)) else __method_missing__(m,*a,&b) end end end end set_var 'a', 42 p a harp:~ > ruby a.rb 42 wow! it __can__ be done. now someone try to break it please! ;-) -a -- =============================================================================== | email :: ara [dot] t [dot] howard [at] noaa [dot] gov | phone :: 303.497.6469 | My religion is very simple. My religion is kindness. | --Tenzin Gyatso ===============================================================================