From: Robert Klemme Date: 2005-03-16T18:34:47+09:00 Subject: Re: eval/binding question "Stefan Kaes" schrieb im Newsbeitrag news:4237F294.5010507@gmx.net... > The current semantics introduces an artificial barrier between code > executed in *eval "code"* vs. just writing *code*, which makes the > semantics more difficult to explain and understand. Ideally, these two > forms should have identical semantics. As I have already explained, the > complexity of variable access increases only for variables whose > declaration point cannot be determined statically and therfore would not > have a negative performance impact on most programs. > > The real world example can be found in Rails. It has a function > render_partial, which takes an erb template name (tn), a value (v) and a > name=>value hash (local_assigns). It makes the value v accessible as a > local variable named "tn" and all name=>value pairs in local_assigns > accessible by their name. This works, because the whole template source > is evaluated using an eval, but requires reparsing of the erb-code each > time the template gets interpreted. And, of course, the code that > implements this function cannot know the names of the local varaiables > in advance. > > As soon as one tries to abstract the erb code into a function the whole > scheme breaks down, because there is no way to dynamically declare local > variables. I solved this problem by resorting to instance variables. > That is okay for me, I just rewrote my template code, but it breaks > backwards compatibility. So this valuable optimisation cannot be > included in Rails, unless everyone rewrites their templates. For this > reason, I have not proposed it to the Rails community. Hm, I'm not 100% sure I modeled this properly, but does this solve the problem? I omitted the template name and the value as these are just special cases of values with fixed names. But you get the picture. And there is no reparsing needed. def local_eval(_values, _code) _val = nil _bnd = binding p local_variables _values.each {|name, val| eval "#{name}=_val", _bnd} p local_variables eval _code, _bnd end >> local_eval( {:x=>1}, "puts x" ) ["_values", "_code", "_val", "_bnd"] ["_values", "_code", "_val", "_bnd", "x"] nil => nil Of course you get some more local variables than you would like to but with proper naming that should not be a problem in practice. Kind regards robert