From: Joel VanderWerf Date: 2008-03-11T15:23:08+09:00 Subject: Re: setting local variables via eval ara howard wrote: > http://drawohara.com/post/28514698 Nice hack, as usual :) Isn't class Object def scope lambda{ } end end enough? You don't need to return binding from the lambda, AFAICT. The lambda never gets called. Also, an alternative to mucking with ObjectSpace: Thread.current[:val] = v definition = "#{ var } = Thread.current[:val]" in place of value = "ObjectSpace._id2ref #{ v.object_id }" definition = "#{ var } = #{ value }" Of course, the value of Thread.current[:val] should be saved and restored. Maybe this makes the hack jruby friendly. There is one case in which the double_quoted_heredoc is not hygienic, when a line of @template begins with __template__: view2 = View.new '__template__' view3 = View.new view2.render puts view3.render But I don't see any hygienic solution (indenting and using <<- doesn't work, because the interpolated strings might have line breaks). Maybe ruby needs a heredoc variant that runs to eof. With these changes, your code becomes: class Object def scope lambda{ } end end class View def initialize template @template = template end def render locals = {} old_val = Thread.current[:val] context = scope locals.each do |k, v| var = k Thread.current[:val] = v definition = "#{ var } = Thread.current[:val]" eval definition, context end double_quoted_heredoc = ['<<__template__', @template, '__template__'].join("\n") eval double_quoted_heredoc, context ensure Thread.current[:val] = old_val end end view = View.new ' #{ x + y } ' puts view.render(:x => 40, :y => 2) #=> 42 -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407