On 2/6/09, Pascal J. Bourguignon <pjb / informatimago.com> wrote: > badboy <badboy / heartofgold.co.cc> writes: > >> Jonathan Wills schrieb: >>> Trying to switch a project of mine from python to ruby. Love ruby so >>> far, but I'm finding that the eval statement is a bit more difficult to >>> use than python's exec statement. Here is one of the problems I'm >>> having, RUBY_VERSION=1.9.1 >>> >>> a = 1 >>> eval('a=2') >>> puts a >>> >>> This will print out '2', as I want. However if I remove the first line, >>> >>> eval('a=2') >>> puts a >>> >>> r.rb:2:in `<main>': undefined local variable or method `a' for >>> main:Object (NameError) >>> >>> >>> Now if in the first case eval can change a variable in its scope, why >>> can't it also create a variable in that same scope? I may also not be >>> totally clear on the way ruby handles scoping, which might be part of >>> what I am having trouble understanding. >>> >>> Any help understanding the eval statement would be appreciated. I will >>> probably have more questions about it, but I'll leave at this for now. >>> >>> thanks, >>> -Jonathan >> why do you want to use eval? >> eval is evil and in most cases not needed in Ruby > > Why are you saying that eval is evil? > > In know that in Common Lisp, EVAL has properties that make its use > dubious in most cases. Mostly it's because it works in the global > environment. > > But this is not the case of eval in Ruby. Since there's no compiler, > they can execute eval in the local lexical environment. So is there > remaining any evilness I don't know? Without taking additional special care, restricting eval to the to a particular binding doesn't contain it very much. eval can, unless something is done to stop it, get access to every Object in the top level environment. For example try running this in irb: hash = Hash.new object = Object.new def object.get_binding binding end b = object.get_binding eval('ObjectSpace.each_object {|o| next if o.frozen?; begin def o.inspect; "pwned"; end; rescue TypeError; end}',a) hash #=>pwned If you run untrusted code in eval without being extra careful, it can reach out of the binding its in and stomp over other objects, even outside of that binding.