Exercise in Frustration

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!

2009/2/15 Trans [email protected]:

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

On Sun, Feb 15, 2009 at 2:43 PM, Trans [email protected] wrote:
This is pretty much the simplest I could come up with

http://pastie.org/389760

an interesting pattern indeed.

HTH
Robert

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: inherit_from_self.rb · GitHub. It’s a
pretty
big hack but lets you write modules that override the behaviour of
classes
they’re mixed into.

On Feb 15, 9:49 am, Pit C. [email protected] wrote:

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):

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=anise.git;a=tree;f=lib/anise;h=d64d5a9ecef1c1b8e1c76a7d84c8462f3aad7ee6;hb=HEAD

Thanks,
T.

On Feb 15, 10:45 am, Robert D. [email protected] wrote:

On Sun, Feb 15, 2009 at 2:43 PM, Trans [email protected] wrote:

This is pretty much the simplest I could come up with

http://pastie.org/389760

an interesting pattern indeed.

That was fast :slight_smile:

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=anise.git;a=blob;f=lib/anise/attribute.rb;h=de5f6e05b0a444ee9de3f4130f6f5573a5f38299;hb=HEAD

Thanks Robert,
T.

2009/2/16 Trans [email protected]

I came up with this a while ago:inherit_from_self.rb · 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.

On Mon, Feb 16, 2009 at 3:18 AM, James C. [email protected]
wrote:

 include MyEnhancement

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/schaerli-phd.pdf

and I have implemented it here:
http://rubyforge.org/projects/ruby-traits/

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

On Feb 15, 2:17 pm, James C. [email protected] wrote:

they’re mixed into.
Sort of like a traits system?

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

T.

On Mon, Feb 16, 2009 at 3:12 AM, Trans [email protected] 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=de5f6e05b0a444ee9de3f4130f6f5573a5f38299;hb=HEAD
Interesting stuff.
R