thought some here might appreciate this
http://drawohara.com/post/28514698
kind regards
ara howard wrote:
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
On Tue, Mar 11, 2008 at 5:20 AM, ara howard [email protected]
wrote:
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 ‘ #{ x + y } ’
puts view.render(:x => 40, :y => 2) #=> 42
Cheers
Robert
–
http://ruby-smalltalk.blogspot.com/
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein
On Mar 11, 2008, at 12:23 AM, Joel VanderWerf wrote:
end
endenough? 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
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
yes. in real code i generate the hdoc in a loop roughly like so
loop {
hdoc =
“__a
#{ rand(230).to_i }__b#{ rand(230).to_i }c#{ rand(2**30).to_i }”
break unless template =~ Regexp.escape(hdoc)
}
etc
great suggestions - the jruby/Thread.current esp.
thx.
On Mar 11, 2008, at 5:28 AM, Robert D. wrote:
end
view = View.new ‘ #{ x + y } ’
puts view.render(:x => 40, :y => 2) #=> 42Cheers
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
v:
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)
;-))
ara howard wrote:
yes. in real code i generate the hdoc in a loop roughly like so
loop {
hdoc = “__a#{ rand(230).to_i }__b#{ rand(230).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
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
On 3/11/08, ara howard [email protected] wrote:
thought some here might appreciate this
http://drawohara.com/post/28514698
kind regards
No need for Object#context
class View
def initialize template
@template = template
end
def render locals = {}
context = binding
locals.each do |k, v|
var = k
value = "ObjectSpace._id2ref #{ v.object_id }"
definition = "#{ var } = #{ value }"
eval definition, context
end
double_quoted_heredoc = ['<<__template__', @template,
‘template’].join(“\n”)
eval double_quoted_heredoc, context
end
end
view = View.new ‘ #{ x + y } ’
puts view.render(:x => 40, :y => 2) #=> 42
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
On Tue, Mar 11, 2008 at 4:52 PM, ara howard [email protected]
wrote:
def initialize template
‘template’].join(“\n”)cfp2:~ > cat a.rb
require ‘yaml’locals = {
‘K’ => ‘or any thing else really’,
‘k’ => %w( list of words ),}
context = binding
context = binding has to be in the render_locals method, so I fail to
understand the point of the example, if
eval ‘x=1’, binding
worked on the top level this thread would not even exist, right?
Robert
–
http://ruby-smalltalk.blogspot.com/
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein
Rick DeNatale wrote:
definition = "#{ var } = #{ value }"
puts view.render(:x => 40, :y => 2) #=> 42
Works just as well.
Not quite.
view = View.new ’ #{ x + y } #{locals} ’
puts view.render(:x => 40, :y => 2) # ==> 42 x40y2
Robert D. 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) #=> 42
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 H…
On 3/11/08, Joel VanderWerf [email protected] wrote:
No need for Object#context
value = “ObjectSpace._id2ref #{ v.object_id }”puts view.render(:x => 40, :y => 2) #=> 42
Works just as well.
Not quite.
view = View.new ‘ #{ x + y } #{locals} ’
puts view.render(:x => 40, :y => 2) # ==> 42 x40y2
Not on my machine:
RubyMate r8136 running Ruby r1.8.6
(/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby)
42 Program exited. -- Rick DeNataleuntitled
My blog on Ruby
http://talklikeaduck.denhaven2.com/
Rick DeNatale wrote:
RubyMate r8136 running Ruby r1.8.6
(/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby)42 Program exited.untitled
I don’t know what’s different about your environment, Rick, but the
point I made elsewhere in this thread is that the version that both
you and Robert offered doesn’t present a clean scope for the added
locals, it just re-uses the local scope of “render”. That means you
can both expand and clobber render’s internal variables, as I showed.
Clifford H…
On 3/11/08, Clifford H. [email protected] wrote:
Not on my machine:
point I made elsewhere in this thread is that the version that both
you and Robert offered doesn’t present a clean scope for the added
locals, it just re-uses the local scope of “render”. That means you
can both expand and clobber render’s internal variables, as I showed.
Oh, OK I missed that subtlety
–
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
On Wed, Mar 12, 2008 at 12:30 AM, Clifford H. [email protected]
wrote:
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 itClifford H…
Thx Clifford this point eluded me, well spotted.
And yes Rick he is right
Robert
–
http://ruby-smalltalk.blogspot.com/
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein
Rick DeNatale wrote:
var = k
view = View.new ’ #{ x + y } ’
Not on my machine:
RubyMate r8136 running Ruby r1.8.6
(/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby)42untitled
Hm. Unless there are at least 2 spaces after the Answer (to the Ultimate
Question et al), you’re not running my two lines of code there… (Even
if locals was nil, you’d still get two spaces.)
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.
Sponsor our Newsletter | Privacy Policy | Terms of Service | Remote Ruby Jobs