[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Exercise in Frustration

Trans

2/15/2009 1:43:00 PM

I would like to see someone else do this. I've simplified the issue to
a small exercise. Given:

module MyEnhancement

def attr_accessor(*a)
put "doing something special with #{a.join(' ')}"
super(*a)
end

end

This module can be used in any class or module simply by using
#extend.

class SomeClass
extend MyEnhancement
end

Great. However, I also want the end-user of this library to be able
effect all classes and modules with a single extend (or include) as
well, if they so choose. Eg.

class Module
include MyEnhancement
end

It would also be nice if the module's methods can be made to work from
the toplevel (main):

extend MyEnhancement

Of course, these last two pieces of code do not work.

In attempting to implement this, I have found myself resorting to
unDRY, ugly, hacky code, that always seems to have a bug in it
somewhere. It's infuriating. This is not how programming Ruby is
supposed to be!



9 Answers

Pit Capitain

2/15/2009 2:50:00 PM

0

2009/2/15 Trans <transfire@gmail.com>:
> Great. However, I also want the end-user of this library to be able
> effect all classes and modules with a single extend (or include) as
> well, if they so choose. Eg.
>
> class Module
> include MyEnhancement
> end

Is the problem here that Module defines its own #attr_accessor
shadowing the new one?

> It would also be nice if the module's methods can be made to work from
> the toplevel (main):
>
> extend MyEnhancement

What should #attr_accessor do in the context of the toplevel object?
Maybe you can show us another example?

> In attempting to implement this, I have found myself resorting to
> unDRY, ugly, hacky code, that always seems to have a bug in it
> somewhere. It's infuriating. This is not how programming Ruby is
> supposed to be!

Hmm, I think this will be hacky indeed.

Regards,
Pit

Robert Dober

2/15/2009 3:45:00 PM

0

On Sun, Feb 15, 2009 at 2:43 PM, Trans <transfire@gmail.com> wrote:
This is pretty much the simplest I could come up with

http://pastie....

an interesting pattern indeed.

HTH
Robert

--
There are some people who begin the Zoo at the beginning, called
WAYIN, and walk as quickly as they can past every cage until they get
to the one called WAYOUT, but the nicest people go straight to the
animal they love the most, and stay there. ~ A.A. Milne (from
Winnie-the-Pooh)

James Coglan

2/15/2009 7:17:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

>
> Great. However, I also want the end-user of this library to be able
> effect all classes and modules with a single extend (or include) as
> well, if they so choose. Eg.
>
> class Module
> include MyEnhancement
> end



I came up with this a while ago: http://gist.github.... It's a pretty
big hack but lets you write modules that override the behaviour of classes
they're mixed into.

Trans

2/16/2009 2:02:00 AM

0



On Feb 15, 9:49=A0am, Pit Capitain <pit.capit...@gmail.com> wrote:
> 2009/2/15 Trans <transf...@gmail.com>:
>
> > Great. However, I also want the end-user of this library to be able
> > effect all classes and modules with a single extend (or include) as
> > well, if they so choose. Eg.
>
> > =A0 =A0class Module
> > =A0 =A0 =A0include MyEnhancement
> > =A0 =A0end
>
> Is the problem here that Module defines its own #attr_accessor
> shadowing the new one?

Yes, that's part of the issue here. In the case where one extends a
class, #super works, in the case of including it into Module, one had
to do the whole alias chaining thing.

As I worked on this it made me think that it would be nice if their
were a MetaKernel for the Module's methods, just as there is a Kernel
for Object's methods. That would at least DRY this part up.

> > It would also be nice if the module's methods can be made to work from
> > the toplevel (main):
>
> > =A0 extend MyEnhancement
>
> What should #attr_accessor do in the context of the toplevel object?
> Maybe you can show us another example?

What it normally does, define a method wrapping an instance variable.
Having it at toplevel isn't that important in this case. But I have a
similar case for an original method (#annotator) where it is.

If the toplevel object were a self extended module, this would not be
an issue either. I know I've brought this up more than a few times,
but I don't recall Matz ever addressing it, and saying why it's not a
good idea. Sure wish I knew, with all the meta-coding I've done this
is one of the few issues I keep bumping my head against.

> > In attempting to implement this, I have found myself resorting to
> > unDRY, ugly, hacky code, that always seems to have a bug in it
> > somewhere. It's infuriating. This is not how programming Ruby is
> > supposed to be!
>
> Hmm, I think this will be hacky indeed.

Unfortunately, what I've managed to get to work very much is. You can
see my hacks for the real deal here:

http://anise.rubyforge.org/git?p=3Danise.git;a=3Dtree;f=3Dlib/anis...
d5a9ecef1c1b8e1c76a7d84c8462f3aad7ee6;hb=3DHEAD

Thanks,
T.

Trans

2/16/2009 2:12:00 AM

0



On Feb 15, 10:45=A0am, Robert Dober <robert.do...@gmail.com> wrote:
> On Sun, Feb 15, 2009 at 2:43 PM, Trans <transf...@gmail.com> wrote:
>
> This is pretty much the simplest I could come up with
>
> http://pastie....
>
> an interesting pattern indeed.

That was fast :-)

I ended up doing something similar to this. Though I wanted to use
#super were I could so I created two versions of the attr_ overrides,
one with #super and one using #alias_method. I also overrode
#append_features instead of using #included. You can see it here:

http://anise.rubyforge.org/git?p=3Danise.git;a=3Dblob;f=3Dlib/an...
bute.rb;h=3Dde5f6e05b0a444ee9de3f4130f6f5573a5f38299;hb=3DHEAD

Thanks Robert,
T.

Trans

2/16/2009 2:13:00 AM

0



On Feb 15, 2:17=A0pm, James Coglan <jcog...@googlemail.com> wrote:
> > Great. However, I also want the end-user of this library to be able
> > effect all classes and modules with a single extend (or include) as
> > well, if they so choose. Eg.
>
> > =A0 =A0class Module
> > =A0 =A0 =A0include MyEnhancement
> > =A0 =A0end
>
> I came up with this a while ago:http://gist.github.... It's a pret=
ty
> big hack but lets you write modules that override the behaviour of classe=
s
> they're mixed into.

Sort of like a traits system?

Thanks James. I'll have a look at this.

T.

James Coglan

2/16/2009 2:18:00 AM

0

[Note: parts of this message were removed to make it a legal post.]

2009/2/16 Trans <transfire@gmail.com>

>
>
> On Feb 15, 2:17 pm, James Coglan <jcog...@googlemail.com> wrote:
> > > Great. However, I also want the end-user of this library to be able
> > > effect all classes and modules with a single extend (or include) as
> > > well, if they so choose. Eg.
> >
> > > class Module
> > > include MyEnhancement
> > > end
> >
> > I came up with this a while ago:http://gist.github.... It's a
> pretty
> > big hack but lets you write modules that override the behaviour of
> classes
> > they're mixed into.
>
> Sort of like a traits system?



I'm afraid I don't know enough about traits and how they differ from mixins
to be able to answer that. In fact, if you know of any good reference
material on traits I'd quite like to give it a read.

Robert Dober

2/16/2009 9:47:00 AM

0

On Mon, Feb 16, 2009 at 3:18 AM, James Coglan <jcoglan@googlemail.com> wrote:
> 2009/2/16 Trans <transfire@gmail.com>
>
>>
>>
>> On Feb 15, 2:17 pm, James Coglan <jcog...@googlemail.com> wrote:
>> > > Great. However, I also want the end-user of this library to be able
>> > > effect all classes and modules with a single extend (or include) as
>> > > well, if they so choose. Eg.
>> >
>> > > class Module
>> > > include MyEnhancement
>> > > end
>> >
>> > I came up with this a while ago:http://gist.github.... It's a
>> pretty
>> > big hack but lets you write modules that override the behaviour of
>> classes
>> > they're mixed into.
>>
>> Sort of like a traits system?
>
>
>
> I'm afraid I don't know enough about traits and how they differ from mixins
> to be able to answer that. In fact, if you know of any good reference
> material on traits I'd quite like to give it a read.
Sure, the cannonical text can be found here:
http://www.iam.unibe.ch/~scg/Archive/PhD/schaer...

and I have implemented it here:
http://rubyforge.org/projects/ru...

N.B. For 1.9 the implementation becomes even simpler.
Cheers
R.

Robert Dober

2/16/2009 10:26:00 AM

0

On Mon, Feb 16, 2009 at 3:12 AM, Trans <transfire@gmail.com> wrote:

>
> I ended up doing something similar to this. Though I wanted to use
> #super were I could so I created two versions of the attr_ overrides,
> one with #super and one using #alias_method. I also overrode
> #append_features instead of using #included. You can see it here:
Ah interesting, that would cover extend too, right?
>
> http://anise.rubyforge.org/git?p=anise.git;a=blob;f=lib/anise/attribute.rb;h=de5f6e05b0a444ee9de3f4130f6f5573a5f382...
Interesting stuff.
R
--
There are some people who begin the Zoo at the beginning, called
WAYIN, and walk as quickly as they can past every cage until they get
to the one called WAYOUT, but the nicest people go straight to the
animal they love the most, and stay there. ~ A.A. Milne (from
Winnie-the-Pooh)