[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Save me from the method_missing

Trans

7/16/2006 4:07:00 AM

I'm find the the whole method_missing, privative clashing methods,
except essential ones, call send otherwise . . . is just a pain. The
whole thing is just to have that nice interface "obj.foo, obj.foo=x".
That might not seem like much but it really stand out in contrast:

obj[:a][:b][:c] -vs- obj.a.b.c

So, dang, if that's all we want, some beauty in our code, and the whole
method_missing thing is just too problematic why not just have another
means? Anuone having a look at Hpricot recently will note the
x/:a/:b/:c notation. No bad, that almost as nice. Okay, step back ...

I was thinking... soon we will become acustom to space significance
with the new Hash notation

{ x: :a } != { x::a }

If we're gogin to be dealing with space significance here anyway, why
not go with it give us the ability to reusue ':'?

class X < Hash

# parameter is always a symbol

def :(x)
self[x]
end

def :=(x,y)
self[x] = y
end

def x(n)
n
end

end

x = X
x:y = 4
x:y #=> 4
x(:y) #=> :y
x :y #=> :y

So then we can easily do

obj:a:b:c

That's just about as nice. Of course the disadvantage is that it's not
very ducky --if you take my meaning. Of course, thinking about that,
one might be inclined to ask, why not just have a special Dispatcher
superclass?

class MyClass < Dispatcher

# only two methods allowed

def .(x, *args, &blk)
...
end

def .=(x,y)
...
end

end

If only .... then I wouldn't be in so deep. Someone save me!

T.


7 Answers

rubyfan

7/16/2006 4:55:00 AM

0

On 7/15/06, transfire@gmail.com <transfire@gmail.com> wrote:
> I'm find the the whole method_missing, privative clashing methods,
> except essential ones, call send otherwise . . . is just a pain. The
> whole thing is just to have that nice interface "obj.foo, obj.foo=x".
> That might not seem like much but it really stand out in contrast:
>
> obj[:a][:b][:c] -vs- obj.a.b.c
>
> So, dang, if that's all we want, some beauty in our code, and the whole
> method_missing thing is just too problematic why not just have another
> means? Anuone having a look at Hpricot recently will note the
> x/:a/:b/:c notation. No bad, that almost as nice. Okay, step back ...
>
> I was thinking... soon we will become acustom to space significance
> with the new Hash notation
>
> { x: :a } != { x::a }
>
> If we're gogin to be dealing with space significance here anyway, why
> not go with it give us the ability to reusue ':'?
>
> class X < Hash
>
> # parameter is always a symbol
>
> def :(x)
> self[x]
> end
>
> def :=(x,y)
> self[x] = y
> end
>
> def x(n)
> n
> end
>
> end
>
> x = X
> x:y = 4
> x:y #=> 4
> x(:y) #=> :y
> x :y #=> :y
>
> So then we can easily do
>
> obj:a:b:c
>
> That's just about as nice. Of course the disadvantage is that it's not
> very ducky --if you take my meaning. Of course, thinking about that,
> one might be inclined to ask, why not just have a special Dispatcher
> superclass?
>
> class MyClass < Dispatcher
>
> # only two methods allowed
>
> def .(x, *args, &blk)
> ...
> end
>
> def .=(x,y)
> ...
> end
>
> end
>
> If only .... then I wouldn't be in so deep. Someone save me!


So what is it exactly that you're trying to do? Are you creating a
DSL, or something?

method_missing can certainly have it's problems and it needs to be
used with care, but I'm certainly glad it's there.

Phil

Trans

7/16/2006 10:36:00 AM

0


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.

T.

Ara.T.Howard

7/16/2006 3:55:00 PM

0

Trans

7/16/2006 7:03:00 PM

0

hi ara,

> ara.t.howard@noaa.gov wrote:

good food for thought. thanks ara. ...

> 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:
>
[snip]
> 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.

yea that's a nice implemementation esspecially for it's simplicity.
while i *tend* toward your opinion there are couple of problems. the
big one is of course my end users really likes the dot notation. and i
can understand, it certainly has a certain elegance and ease to it.
unfortunately it's a nightmare to code. btw, the notation X.ann(:x)
does work already in what I have, but another thing is this use:

X.ann :a, :b, :c, :class => String

X.ann.a.class #=> String
X.ann.b.class #=> String
X.ann.c.class #=> String

Also there's a shortcut for setting the :class annotation.

X.ann :a, :b, :c, String

I imagine that still can be worked in to your impl, but it does starts
to get a little thicker.

I should also note that it's not just annotations, I use it lots else
where too. I esspecially like using Facets' OpenCascade on YAML load
configs.

s = %{
a:
b:
c: "abc"
}

data = OpenCascade[ YAML.load(s) ]

data.x.y.z #=> "abc"

(OT. Notice BTW how I use ::[] on OpenCascade. It's a subclass of Hash.
In an earlier post I mentioned how I felt that ::new should be able to
take a hash rather than a default value --well there's why. I actually
just spent ~2 hours tracknig a bug that came down to using ::new when I
should have used []. That sucked!)

> 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.

You're right about that. There are limitations to using method_missing.
Though I don't mind so much if the limitations are *well defined* and
minimial, but the current state of affairs is too iffy.

> 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...

Well, that could be solved with a special interface, eg.

klass.ann.cascade_send *args

or something. But it's a good point too.

T.


Ara.T.Howard

7/17/2006 3:32:00 PM

0

Trans

7/17/2006 4:09:00 PM

0


ara.t.howard@noaa.gov wrote:

> yikes. i've done exactly this kind of this many times but i'm tending away
> from it. the reason is that the spec just doesn't quite fit when s is defined
> thusly:
>
> s = <<-yml
>
> "hard to use" : "forty-two"
>
> 42 : "impossible to use"
>
> "!can't work" : "etc"
>
> yml
>
> i suppose it's ok to contrain configs you have keys that are valid ruby
> methods, still i've just found myself in a corner with that a few times and
> have strayed away from it every since. like i said, i still have lots of code
> doing stuff with method_missing, but i thought i'd put my thought out there
> for posterity and for people starting new designs.

Yes, I do constrain the config keys to single word case insensitive
strings. Unfortuate I just don't see a nicer way. "y[:a][:b][:c]" just
lacks all elegance. And path notation (y/:a/:b/:c) while a _little_
better can't use setting at the end (eg. y/:a/:b/:c = x). So what else
is there?

> > You're right about that. There are limitations to using method_missing.
> > Though I don't mind so much if the limitations are *well defined* and
> > minimial, but the current state of affairs is too iffy.
>
> what do you mean 'iffy' exactly?

Well, for instance. If a public method is added to Kernel or Object (or
any subclass for that matter) it will show up in ones class and block
out method_missing.

> that the list of 'require' methods seems to change every few months?

Not sure what you mean.

T.


Ara.T.Howard

7/17/2006 5:08:00 PM

0