From: Intransition Date: 2011-11-08T04:13:07+09:00 Subject: Re: Tricky DSL, how to do it? ------=_Part_454_14443894.1320693184523 Content-Type: multipart/alternative; boundary="----=_Part_455_25769159.1320693184523" ------=_Part_455_25769159.1320693184523 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On Monday, November 7, 2011 9:14:44 AM UTC-5, Sean O'Halpin wrote: > > You could capture the calling self by getting it from the binding of > the block and hide the evaluating call behind your own #eval method: > > class Evaluator < BasicObject > def initialize(&block) > @__config__ = {} > if block > @context = block.binding.eval("self") > instance_eval(&block) > end > end > > def __config__ > @__config__ > end > > def method_missing(sym, *args, &block) > @__config__[sym] = block > end > > def eval(sym, *args) > @context.instance_exec(*args, &@__config__[sym]) > end > > end > > e = Evaluator.new do > foo do > puts "foo" > end > > bar do |txt| > puts "txt = #{txt}" > end > end > > e.eval(:foo) # => "foo" > e.eval(:bar, "hello") # => "txt = hello" > Nicely coded. And spot on. If I didn't know that self would always be toplevel in my particular case this is the code I would be using. Actually... this code seems like it might make for a good general use DSL pattern. I'm going to try to generalize it further and see if makes sense to make it a reusable library. What do you think? ------=_Part_455_25769159.1320693184523 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

On Monday, November 7, 2011 9:14:44 AM UTC-5, Sean O'Halpin wrote:<= blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord= er-left: 1px #ccc solid;padding-left: 1ex;">

You could capture the callin= g self by getting it from the binding of
the block and hide the evaluati= ng call behind your own #eval method:

class Evaluator < BasicObjec= t
  def initialize(&block)
    @__config__ =3D {}<= br>    if block
      @context =3D block.bindin= g.eval("self")
      instance_eval(&block)
  =   end
  end

  def __config__
    @__co= nfig__
  end

  def method_missing(sym, *args, &block= )
    @__config__[sym] =3D block
  end

  de= f eval(sym, *args)
    @context.instance_exec(*args, &@__c= onfig__[sym])
  end

end

e =3D Evaluator.new do
 = ; foo do
    puts "foo"
  end

  bar do |txt= |
    puts "txt =3D #{txt}"
  end
end

e.eval(= :foo)               # =3D> "foo"
e= .eval(:bar, "hello")    # =3D> "txt =3D hello"

Nicely coded. And spot on. If I didn't know that self would always be= toplevel in my particular case this is the code I would be using. 

Actually... this code seems like it might make for a= good general use DSL pattern. I'm going to try to generalize it further an= d see if makes sense to make it a reusable library. 

What do you think?

------=_Part_455_25769159.1320693184523-- ------=_Part_454_14443894.1320693184523--