thought some here might appreciate this
http://drawohara.com/post/28514698
kind regards
···
--
share your knowledge. it's a way to achieve immortality.
h.h. the 14th dalai lama
thought some here might appreciate this
http://drawohara.com/post/28514698
kind regards
--
share your knowledge. it's a way to achieve immortality.
h.h. the 14th dalai lama
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 '<body> #{ x + y } </body>'
puts view.render(:x => 40, :y => 2) #=> <body> 42 </body>
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
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
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
--
http://ruby-smalltalk.blogspot.com/
---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein
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 '<body> #{ x + y } </body>'
puts view.render(:x => 40, :y => 2) #=> <body> 42 </body>
Works just as well.
On 3/11/08, ara howard <ara.t.howard@gmail.com> wrote:
thought some here might appreciate this
http://drawohara.com/post/28514698
kind regards
--
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
ara howard wrote:
Nice hack, as usual
Isn't
class Object
def scope
lambda{ }
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
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.renderBut 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.
On Mar 11, 2008, at 12:23 AM, Joel VanderWerf wrote:
--
sleep is the best meditation.
h.h. the 14th dalai lama
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
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 courseclass View
def initialize template
@template = template
enddef 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
endview = View.new '<body> #{ x + y } </body>'
puts view.render(:x => 40, :y => 2) #=> <body> 42 </body>Cheers
Robert
---
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
i just realized that
def scope
binding
end
is what i am acually using - sorry for confusion
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.
--
share your knowledge. it's a way to achieve immortality.
h.h. the 14th dalai lama
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.
Rick DeNatale wrote:
On 3/11/08, ara howard <ara.t.howard@gmail.com> 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
enddef 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
endview = View.new '<body> #{ x + y } </body>'
puts view.render(:x => 40, :y => 2) #=> <body> 42 </body>
Works just as well.
Not quite.
view = View.new '<body> #{ x + y } #{locals} </body>'
puts view.render(:x => 40, :y => 2) # ==> <body> 42 x40y2 </body>
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
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
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?
<skipped rest of example>
Robert
On Tue, Mar 11, 2008 at 4:52 PM, ara howard <ara.t.howard@gmail.com> wrote:
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
> Robertcfp2:~ > cat a.rb
require 'yaml'locals = {
'K' => 'or any thing else really',
'k' => %w( list of words ),}
context = binding
--
http://ruby-smalltalk.blogspot.com/
---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein
Rick DeNatale wrote:
>> thought some here might appreciate this
>>
>> http://drawohara.com/post/28514698
>>
>> kind regards
>>
>> a @ http://codeforpeople.com/
>
> 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 '<body> #{ x + y } </body>'
>
> puts view.render(:x => 40, :y => 2) #=> <body> 42 </body>
>
> Works just as well.Not quite.
view = View.new '<body> #{ x + y } #{locals} </body>'
puts view.render(:x => 40, :y => 2) # ==> <body> 42 x40y2 </body>
Not on my machine:
RubyMate r8136 running Ruby r1.8.6
(/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby)
untitled
<body> 42 </body>
Program exited.
On 3/11/08, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:
> On 3/11/08, ara howard <ara.t.howard@gmail.com> wrote:
--
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
Thx Clifford this point eluded me, well spotted.
And yes Rick he is right
Robert
On Wed, Mar 12, 2008 at 12:30 AM, Clifford Heath <no@spam.please.net> wrote:
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 itClifford Heath.
--
http://ruby-smalltalk.blogspot.com/
---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein
Rick DeNatale wrote:
On 3/11/08, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:
Rick DeNatale wrote:
> On 3/11/08, 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/
>
> 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 '<body> #{ x + y } </body>'
>
> puts view.render(:x => 40, :y => 2) #=> <body> 42 </body>
>
> Works just as well.Not quite.
view = View.new '<body> #{ x + y } #{locals} </body>'
puts view.render(:x => 40, :y => 2) # ==> <body> 42 x40y2 </body>Not on my machine:
RubyMate r8136 running Ruby r1.8.6
(/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby)untitled
<body> 42 </body>
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.)
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
Rick DeNatale wrote:
On 3/11/08, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:
Rick DeNatale wrote:
> On 3/11/08, ara howard <ara.t.howard@gmail.com> wrote:
Not quite.view = View.new '<body> #{ x + y } #{locals} </body>'
puts view.render(:x => 40, :y => 2) # ==> <body> 42 x40y2 </body>Not on my machine:
RubyMate r8136 running Ruby r1.8.6
(/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby)untitled
<body> 42 </body>
Program exited.
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 Heath.
Oh, OK I missed that subtlety
On 3/11/08, Clifford Heath <no@spam.please.net> wrote:
Rick DeNatale wrote:
> On 3/11/08, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:
>> Rick DeNatale wrote:
>> > On 3/11/08, ara howard <ara.t.howard@gmail.com> wrote:>> Not quite.
>>
>> view = View.new '<body> #{ x + y } #{locals} </body>'
>> puts view.render(:x => 40, :y => 2) # ==> <body> 42 x40y2 </body>
>
> Not on my machine:
>
> RubyMate r8136 running Ruby r1.8.6
> (/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby)
>>>> untitled
>
> <body> 42 </body>
> Program exited.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.
--
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/