Yukihiro Matsumoto wrote:
> I still have difficulties to imagine the concrete situation.
>
> |  module M
> |    class << self
> |      attr_accessor :foo
> |    end
> |    def foo
> |      self.class.foo
> |    end
> |  end
>
> Do we have to allow M.foo?  I fell like you need to a way to add class
> methods and instance methods at once, but it doesn't have to (or maybe
> it shouldn't) be module methods inclusion.
>
> |It's a class level setting, but with a way to easily access it from the
> |instance level. To split this up into two modules is clearly a forced
> |concession.
> |
> |  module Mc
> |      attr_accessor :foo
> |  end
> |
> |  module Mi
> |    def foo
> |      self.class.foo
> |    end
> |  end
> |
> |  class X
> |    extend Mc
> |    include Mi
> |  end
>
> If you don't need M.foo and M.foo= in above example (while you
> definitely need X.foo and X.foo=), Mc and Mi solution is the way to
> go.  Redundancy can be removed by some kind of meta programming.

The problem runs deeper than this. Having to depend on "some kind of
meta programming" is not as simple as it might seem. The complexity can
grow. Take for example my implementation of Annotations. Ex-

  module M
    def x ; "foo" ; end
    ann :x, :type => String
  end

  class X
    include M
  end

An annotation stores metadata about instance methods and hence accessed
at the class-level. They are also "inheritable", ie. class X refers
back to M's annotations:

  X.a_x  #=> #<Annotation type=String>

This is a clear example of where the instance-level is tied to the
class-level in such a way that they must both go along with each other.

In my experience the main thing that drives us to use ClassMethods and
like "hacks" is not  that it can't be done using a two module
extend/include approach, but becuase we don't want to trouble our users
with the differentiation -- docs like:

  NOTE: This module is designed to be used with #extend (not #include)
  when  "extending" classes (though you must use #include when
  "extending" it to modules which subsequently must then also use
  #extend).

This may seem excessive, but not everyone is a Ruby expert. And it only
becomes worse to tell someone thay have to both #include the module AND
#extend it's extensible counter-part module to get full functionality.

As you say, meta-programming can take care of it, but the biggest
problem with meta-programming approaches is that everyone is using
there own variation. They may use #included, they may override
#append_features, they may override #include itself, or some other
trick. And like I've said I've seen code go so far as to paste methods
directly into a class via the included callback --all becuase this
distiinctin between extend and include and how to handle it (or hack it
as the case may be) was clear to the programmer. 

T.