PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > comp.lang.ruby > setting local variables via eval
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
setting local variables via eval

Réponse
 
LinkBack Outils de la discussion
Vieux 11/03/2008, 05h20   #1
ara howard
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut setting local variables via eval


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



  Réponse avec citation
Vieux 11/03/2008, 07h23   #2
Joel VanderWerf
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut 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 '<body> #{ x + y } </body>'

puts view.render(:x => 40, :y => 2) #=> <body> 42 </body>


--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

  Réponse avec citation
Vieux 11/03/2008, 12h28   #3
Robert Dober
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: setting local variables via eval

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

  Réponse avec citation
Vieux 11/03/2008, 16h48   #4
ara howard
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: setting local variables via eval


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




  Réponse avec citation
Vieux 11/03/2008, 16h52   #5
ara howard
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: setting local variables via eval


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




  Réponse avec citation
Vieux 11/03/2008, 17h01   #6
ara howard
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: setting local variables via eval


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



  Réponse avec citation
Vieux 11/03/2008, 18h52   #7
Joel VanderWerf
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: setting local variables via eval

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

  Réponse avec citation
Vieux 12/03/2008, 00h27   #8
Clifford Heath
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: setting local variables via eval

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.
  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 13h44.


Édité par : vBulletin® version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,29955 seconds with 16 queries