Yukihiro Matsumoto wrote:

>|What would be bad about allowing the include method to take Classes in 
>|addition to Modules? (And to keep everything else the same, including 
>|the distinction between subclassing (via "<") and mixin-ing (via 
>|"include").)
>
>If we allow "include" to take classes, it's a plain multiple
>inheritance.
>
If that were true, then your previous statement wouldn't be true:
"Besides that, there's no diamond inheritance in Mixin inheritance."

If we make the include method act the same on Classes as it does on 
Modules (that is, to call #append_features, which, in turn, adds the 
constants, methods, and module variables of the included class to the 
receiving class), then that's just Mixin inheritance on Class objects.

>  We should stand all the complexity of multiple
>inheritance by that.
>
I don't see "module Enumerable; ... end" as being simpler than "class 
Enumerable; ... end". Am I missing something?

>  I might have misunderstood you since I'm not
>sure what you meant by "keeping everything else the same".
>  
>
Specifically, running include on a Class doesn't modify self.superclass, 
and the super keyword would still try to talk to the actual superclass, 
and not anything being mixed in, just like is the case with Modules. 
Probably other things, too, but my mind is a little fuzzy right now.

Granted, weird things would happen if someone tried to include Array, 
but weird things happen now when someone tries to subclass Array. 
Allowing Classes to be included would be backward compatible (except for 
code that actually _intends_ to raise a TypeError), and so your core and 
std libs would be the same. As such, I don't see the comparison to C++'s 
wacky IO inheritance graph as valid.

Well, even if your mind is set, matz, I appreciate your listening. In 
all fairness, I /don't/ have a use case waiting in the hangar, should 
classes and modules one day unify. :)

The following is really ugly, and completely untested, but might 
demonstrate my intent:

require 'ruby2ruby' #see http://dark.fhtr.org/ruby2ruby.rb
#or http://blog.zenspider.com/archives/2005/02/rubytoruby.html

class Module
  alias_method :orig_include, :include
  def include(*mods)
    classes, mods = mods.partition {|m| m.is_a? Class}
    classes.each {|klass| klass.append_features(self)}
    orig_include(mods)
  end
end

class Class
  def append_features(mod)
    constants.each {|const| mod.const_set(const,const_get(const))}
    class_variables.each do |var|
      value = eval "@@#{var}"
      mod.class_eval { @@temp = value }
      mod.class_eval "@@#{var} = @@temp"
    end
    instance_methods.each do |meth|
      mod.class_eval instance_method(meth).to_ruby
    end
  end
end

I also might be doing things the stupid ways at times. So sue me.

Thanks,
Devin