On Sun, Nov 6, 2011 at 11:35 PM, Intransition <transfire / gmail.com> wrote:
> I'd want to write a DSL such that a surface method_missing catches undefi=
ned
> methods and records the blocks that they define e.g.
> =A0 foo do
> =A0 =A0 puts "foo"
> =A0 end
> So I would end up with:
> =A0 { :foo=3D>#<Proc ...> }
> Presently I have something like this:
>
> =A0 #
> =A0 class Evaluator < BasicObject
> =A0 =A0 def initialize(&block)
> =A0 =A0 =A0 @__config__ =3D {}
> =A0 =A0 =A0 instance_eval(&block) if block
> =A0 =A0 end
> =A0 =A0 def __config__
> =A0 =A0 =A0 @__config__
> =A0 =A0 end
> =A0 =A0 def method_missing(sym, *args, &block)
> =A0 =A0 =A0 @__config__[sym] =3D block
> =A0 =A0 end
> =A0 end
> However when I call on a block I want it to evaluate as if in the definin=
g
> context=A0(in this case toplevel), not inside the "DSL" class that evalua=
ted
> via method_missing.
> =A0 e =3D Evaluator.new do
> =A0 =A0 foo do
> =A0 =A0 =A0 puts "foo"
> =A0 =A0 end
> =A0 end
>
> =A0 e.__config__[:foo].call
> Instead of what I want, I get a method missing error for #puts.
> Any ideas?

You can't have both (evaluate with self =3D Evaluator to trigger
Evaluator's method missing and invoking the block in the defining
context) at the same time.

Question is, what happens if a missing method is invoked?  In your
implementation the block is returned.   I would at least change that
to return nil to avoid nasty side effects.  But generally execution
cannot reasonably continue.  What about catching the exception and
recording it?

12:54:59 ~$ ./x.rb
{:foo=3D>#<Proc:0x101b3554@./x.rb:24>}
12:55:02 ~$ cat -n x.rb
     1  #!/bin/env ruby19
     2
     3  class Evaluator < BasicObject
     4    def initialize(&block)
     5      @__config__ =3D {}
     6
     7      if block
     8        begin
     9          block.call
    10        rescue ::NoMethodError =3D> e
    11          @__config__[e.name] =3D block
    12          nil
    13        end
    14      end
    15    end
    16
    17    def __config__
    18      @__config__
    19    end
    20
    21  end
    22
    23
    24  e =3D Evaluator.new do
    25    foo do
    26      puts "foo"
    27    end
    28  end
    29
    30  p e.__config__
    31
12:55:03 ~$

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/