On Fri, 2004-10-08 at 03:51, trans. (T. Onoma) wrote:
> On Friday 08 October 2004 01:49 am, nobu.nokada / softhome.net wrote:
> | Hi,
> |
> | At Tue, 5 Oct 2004 03:51:20 +0900,
> |
> | trans.  (T. Onoma) wrote in [ruby-talk:114847]:
> | > I see. So this kind of thing just can't happen I take it. (Hmm... I think
> | > we discussed this kind of thing on core once.) It would be nice if we
> | > could pass in locals to the binding:
> | >
> | >   eval(tb, a) { |a| cool = a.call(cool) }
> | >
> | > It might also be nice if this could be done without "stepping on toes"
> | > (i.e. overwriting binding's locals).
> |
> | eval("proc{|cool|}", tb).call(a.call(eval("cool", tb)))
> 
> What are you?  
> 
> (Note: if this statement doesn't cross the language barrier well, just know 
> that it is a big compliment!)

I agree.  That's a very clever hack.

irb> class T
irb>     def initialize
irb>      @x = 1
irb>    end
irb>    attr_reader :x
irb>    def get_binding
irb>      cool = "matz"
irb>      return binding()
irb>    end
irb>  end
=> nil
irb>  t = T.new
=> #<T:0x400bee3c @x=1>
irb>  tb = t.get_binding
=> #<Binding:0x400b85a0>
irb> eval "cool",tb
=> "matz"
irb> a = proc { |s| s.upcase }
=> #<Proc:0x400b0abc@(irb):33>
irb> eval("proc{|cool|}", tb).call(a.call(eval("cool", tb)))
=> nil
irb> eval "cool",tb
=> "MATZ"

So basically, what you have is a getter:

                                                 vvvvvvvvvvvvvvv
eval("proc{|cool|}", tb).call(a.call(eval("cool", tb)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

and a setter.  We could even abstract them (baby steps here; I realize
this opens up all sorts of possibilities):

def tb.[](v)
    eval(v.to_s,self)
    end

def tb.[]=(v,x)
    eval("proc{|#{v}|}",self).call(x)
    end

(Using []= also gives us the assignment chaining semantics).

Very nifty!

-- Markus