On Sun, 16 Jul 2006, Trans wrote:

> Phil Tomson wrote:
>
>> So what is it exactly that you're trying to do?  Are you creating a
>> DSL, or something?
>
> Basically, albiet a lower-level sort of one. It all goes back to
> Facet's Annotations lib. Annotations work like this:
>
>  class X
>    ann :x, :class => String, :default => 10, :foo => :bar
>  end
>
>  X.ann.x.class #=> String
>  X.ann.x.default #=> 10
>  X.ann.x.foo #=> :bar
>
>  X.ann.x.foo  = :baz
>  X.ann.x.foo #=> :baz
>
>  X.ann.x => #<Annotation(X#x) {:class => String, :default => 10, :foo
> => :baz}>
>
> Annotation class is a subclass of OpenObject, which is much like
> OpenStruct, but it dynamically prevents method visibility --hence my
> previous post on #private_filter. And I need that to ensure no new
> methods pop up that would interfere with OpenObject's functionality.
> For example:
>
>  o = OpenObject.new
>  o.yep = 10
>  o.yep  #=> 10
>
> and then, someone else comes along:
>
>  class Object
>    def yep ; "your sunk" ; end
>  end
>
> My method_missing in OpenObject wouldn't catch #yep anymore and she'd
> be sunk.
>
>> method_missing can certainly have it's problems and it needs to be
>> used with care, but I'm certainly glad it's there.
>
> No doubt. No suggestion here of getting rid, or anything of the sort.
> Just looking for a sounder means for the above type of usecase.

hi tom-

i use method_missing too but, in this case, you'd have to provide an extremely
strong argument why an interface like this won't suffice:

   harp:~ > cat a.rb
   class Module
     def ann meth, arg = nil
       @ann ||= {}
       if Hash === arg
         arg ? (@ann[meth] ||= {}).update(arg) : @ann[meth]
       else
         arg ? @ann[meth][arg] : @ann[meth]
       end
     end
   end

   class X
     ann :x, :class => String, :default => 10, :foo => :bar
   end

   X.ann :x, :class   #=> String
   X.ann :x, :default #=> 10
   X.ann :x, :foo     #=> :bar

   X.ann :x           #=> #<Annotation(X#x) {:class => String, :default => 10, :foo > :baz}>


   harp:~ > ruby -W0 a.rb
   String
   10
   :bar
   {:default=>10, :class=>String, :foo=>:bar}


it's simple and rather concise - adding only a char or so.  more importanlty,
however, the impl above actually conforms to the specification i imagine your
annotation class requires, which is that __any__ token might be used as an
annotation tag, for instance

   ann 'x', __id__ => method('x').__id__

which no method_missing approach will ever quite be able to skin.

anyhow - just playing devil's advocate - but i think it's an important
consideration.

cheers.

ps.

   klass.ann.x.prop

becomes much longer if the arg list is in a variable, for instance, with my
impl above it would be

   args = %w( x prop )

   klass.ann *args

but, using a method_missing approach it becomes

   args = %w( x prop )

   klass.ann.send(args.first).send(args.last)

this applies to many method_missing approaches: they are more consise until
another layer of abstraction is added, like having the methods be read from a
config file, food for thought...


-a
-- 
suffering increases your inner strength.  also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama