From: ptkwt@... (Phil Tomson) Date: 2006-02-17T07:38:27+09:00 Subject: Re: recontextualizing a block (looking for deep magic) In article <5cd596d60602161330o67494818oadaad45229662f5c@mail.gmail.com>, Jim Freeze wrote: >On 2/16/06, Phil Tomson wrote: >> What I'm trying to do probably isn't possible, but maybe someone knows so= >me >> deep magic. >> >> I'd like something like: >> >> def runit &b >> a =3D 42 >> pnew =3D Proc.new &b, binding >> pnew.call >> end >> >> runit { puts "a is: #{a}" } >> >> #would print: >> a is: 42 >> >> Or course, Proc.new currently doesn't take a Binding object second argume= >nt. >> What I'm wondering is if there is any way to 'rebind' or 'recontextualize= >' a >> block? > >This is interesting. For a while you had me thinking the Proc.new {} should >rebind, but I couldn't get it to. Seems that the binding is based upon wher= >e the >block is defined inside the file. Right. And 99% of the time that's what you want because they're closures. .... but sometimes I find I want the block evaluation to be delayed and done in a different binding. I think a Proc.new that took a binding would be useful sometimes, but I'm not hopeful that it could be implemented without mucking around with Ruby's internals (in C). > >This is the closest I could get: > > def runit(b) > a =3D 42 > pnew =3D lambda { eval(b,binding) } > pnew.call > end > > runit %q{ puts "a is: #{a}" } > Yeah, I eventually came up with pretty-much the same thing. This is probably what I'll end up doing since: %q{ ... } doesn't look all that different from the regular block syntax: { ... } ....but as this is for a DSL, I'm sure users are going to be thinking "what the heck is the %q for?" and I don't blame them. It hurts the aesthetics. Phil