|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
thought some here might appreciate this http://drawohara.com/post/28514698 kind regards a @ http://codeforpeople.com/ -- share your knowledge. it's a way to achieve immortality. h.h. the 14th dalai lama |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
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 '<body> #{ x + y } </body>' puts view.render(:x => 40, :y => 2) #=> <body> 42 </body> -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407 |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Tue, Mar 11, 2008 at 5:20 AM, ara howard <ara.t.howard@gmail.com> wrote:
> > thought some here might appreciate this > > http://drawohara.com/post/28514698 > > kind regards > > a @ http://codeforpeople.com/ > -- > share your knowledge. it's a way to achieve immortality. > h.h. the 14th dalai lama > > > > Ara Obviously I miss something, but I have the feeling that this simplification still works, which use cases did I miss? The idea is crazy of course ![]() class View def initialize template @template = template end def render locals = {} context = binding locals.each do |k, v| definition = "#{ k } = #{ v }" eval definition, context end double_quoted_heredoc = ['<<__template__', @template, '__template__'].join("\n") eval double_quoted_heredoc, context end end view = View.new '<body> #{ x + y } </body>' puts view.render(:x => 40, :y => 2) #=> <body> 42 </body> Cheers Robert -- http://ruby-smalltalk.blogspot.com/ --- Whereof one cannot speak, thereof one must be silent. Ludwig Wittgenstein |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On Mar 11, 2008, at 12:23 AM, Joel VanderWerf wrote: > 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. that's what i head originally - but blows up in 1.9 which requires a binding > > > 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. > oh very nice. yeah, pushing and popping from Thread.current is very good > 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. > yes. in real code i generate the hdoc in a loop roughly like so loop { hdoc = "__a #{ rand(2**30).to_i }__b#{ rand(2**30).to_i }__c#{ rand(2**30).to_i }__" break unless template =~ Regexp.escape(hdoc) } etc great suggestions - the jruby/Thread.current esp. thx. a @ http://drawohara.com/ -- sleep is the best meditation. h.h. the 14th dalai lama |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
On Mar 11, 2008, at 5:28 AM, Robert Dober wrote: > Ara > > Obviously I miss something, but I have the feeling that this > simplification still works, which use cases did I miss? > The idea is crazy of course ![]() > > class View > def initialize template > @template = template > end > > def render locals = {} > context = binding > locals.each do |k, v| > definition = "#{ k } = #{ v }" > eval definition, context > end > double_quoted_heredoc = ['<<__template__', @template, > '__template__'].join("\n") > eval double_quoted_heredoc, context > end > end > > view = View.new '<body> #{ x + y } </body>' > puts view.render(:x => 40, :y => 2) #=> <body> 42 </body> > > Cheers > Robert cfp2:~ > cat a.rb require 'yaml' locals = { 'K' => 'or any thing else really', 'k' => %w( list of words ), } context = binding locals.each do |k, v| begin definition = "#{ k } = #{ v }" y 'k' => k, 'v' => v, 'definition' => definition eval definition, context rescue Object => e y 'error' => "#{ e.message } (#{ e.class })" end end cfp2:~ > ruby a.rb --- v: - list - of - words k: k definition: k = listofwords --- error: undefined local variable or method `listofwords' for main:Object (NameError) --- v: or any thing else really k: K definition: K = or any thing else really --- error: |- compile error b.rb:8: syntax error, unexpected kOR K = or any thing else really ^ (SyntaxError) ;-)) a @ http://drawohara.com/ -- sleep is the best meditation. h.h. the 14th dalai lama |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
On Mar 11, 2008, at 12:23 AM, Joel VanderWerf wrote: > enough? You don't need to return binding from the lambda, AFAICT. > The lambda never gets called. i just realized that def scope binding end is what i am acually using - sorry for confusion a @ http://codeforpeople.com/ -- share your knowledge. it's a way to achieve immortality. h.h. the 14th dalai lama |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
ara howard wrote:
> yes. in real code i generate the hdoc in a loop roughly like so > > loop { > hdoc = "__a#{ rand(2**30).to_i }__b#{ rand(2**30).to_i }__c#{ > rand(2**30).to_i }__" > > break unless template =~ Regexp.escape(hdoc) > } Or: hdoc = "__template" while /^#{hdoc}/ =~ @template hdoc.succ! p hdoc end double_quoted_heredoc = ["<<#{hdoc}", @template, hdoc].join("\n") eval double_quoted_heredoc, context -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407 |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
Robert Dober wrote:
> Obviously I miss something, but I have the feeling that this > simplification still works, which use cases did I miss? > ... > puts view.render(:x => 40, :y => 2) #=> <body> 42 </body> Try running it with the following: puts view.render(:context => 40, :y => 2) #=> TypeError Ara's "scope" method contains no local variables for yours to step on. Nice trick Ara - I always appreciate your insights. I had to play with this one a bit before properly understanding it :-) Clifford Heath. |
|
![]() |
| Outils de la discussion | |
|
|