Thank you for keeping up Ara --- I'm enjoying this
discussion. :-)

"Ara.T.Howard" <Ara.T.Howard / noaa.gov> writes:

> On Thu, 28 Jul 2005, Daniel Brockman wrote:
>
>>> i'd say __all__ code depends on that.  otherwise
>>>
>>>    module M
>>>      def self::new
>>>        raise
>>>      end
>>>    end
>>>    class C
>>>      include M
>>>    end
>>>
>>>    c = C::new
>>
>> Surely you are not suggesting that all code defines
>> singleton °∆new°« methods on modules?

What I meant by this was that your claim, "i'd say __all__
code depends on that," was a bit bold.

>> Considering that this doesn't work,
>>
>>   class X
>>     def self.new
>>       raise
>>     end
>>   end
>>
>>   class Y < X
>>   end
>>
>>   x = X.new
>>
>> why do you expect your example to work?
>
> well - you have to actually __use__ the method - i was
> pointing to the fact that they are inherited in the case
> of subclasses and are not in the case of mixins ;-)

Yes, and I was trying to ask you whether or not and *why*
you expect such a difference in behavior.  (If you didn't
expect it, then you agree it is surprising?)

>    harp:~ > cat a.rb
>    class X
>      def self.new
>        raise
>      end
>    end
>
>    class Y < X
>      def self.new; super; end
>    end
>
>    x = X.new
>
>    harp:~ > ruby a.rb
>    a.rb:3:in `new': unhandled exception
>            from a.rb:11
>
>
>> I don't get why Y's singleton class inherits from X's,
>> while C's *doesn't* inherit from M's.
>
> because otherwise including module could clobber class
> methods which generally include hooks to create instances
> like 'new', 'instance', 'parse', etc.

But you have already demonstrated that inheriting from a
class *can* clobber methods like Class#new.  So I don't see
the difference.  I know *what* happens; just not *why*.

   class AbstractFoo
     def self.new
       raise "nope!"
     end
   end

   class Foo < AbstractFoo
   end

   foo = Foo.new # error

   class Foo
     def self.new
       # What do I put here?
     end
   end

Clearly this problem already exists for class inheritance.

> if you replace the set of methods responsible for stamping
> out instances you are not 'mixing-in' functionality to
> those instances -

(No, you are mixing in functionality to the *class*, not the
instances, though of course the latter refer to the former.)

> but changing what type those will be.  there is a
> fundemental difference here.

You are making a *classic* bifurcation here:  Your argument
boils down to, "you are changing what type the instances
will have, therefore you are not mixing in functionality,"
when in fact I am doing both.

It's like if I were to say that in your example,

>    class X
>      def self.new
>        raise
>      end
>    end
>
>    class Y < X
>      def self.new; super; end
>    end

the Y class is not inheriting from the X class, because it's
preventing instances from being created.

>> Why are you defining M.new?  Do you have actual code that
>> does this?
>
> tons. [...]
>
>    module Command
>      class Abstract
>        ...
>      end
>      class Load < Abstract
>        ...
>      end
>      class Sub < Abstract
>        ...
>      end
>      class Add < Abstract
>        ...
>      end
>      class Store < Abstract
>        ...
>      end
>      def self::new line
>        orbit_normal_time, command, register, value = parse line
>        klass =
>          case command
>            when /load/
>              Load
>            when /sub/
>              Sub
>            when /add/
>              Add
>            when /store/
>              Store
>          end
>        klass::new(orbit_normal_time, register, value)
>      end
>    end
> 
>    class PayloadActivationMessage < AbstractMessage
>      include Command
>    end

Okay, thank you.  I can see that a lot of similar code
probably exists.  But the example you've given would not be
difficult to fix if module metaclass inheritance were added.

Actually, your code seems pretty fishy to me as it is:

   command = Command.new(foo)
   command.is_a? Command #=> false

I think it would have been a better idea to do this:

   class Command
     class Load < Command
       ...
     end
     class Sub < Command
       ...
     end
     class Add < Command
       ...
     end
     class Store < Command
       ...
     end
     def self::new line
       orbit_normal_time, command, register, value = parse line
       klass =
         case command
           when /load/
             Load
           when /sub/
             Sub
           when /add/
             Add
           when /store/
             Store
         end
       klass::new(orbit_normal_time, register, value)
     end
   end

If you change your code in this way, the problem disappears;
in other words, your code is no longer an example of where
module metaclass inheritance is a problem.

It's useful to see actual code that would break, but it
would be even more useful to see actual, *non-fishy* code
that would break.  So could you share any other examples?

> changing the notion of super is, be definition, a very
> strong form on inheritence.

Then it is your opinion that including a module is a "very
strong form of inheritence"?

> added multiple inheritence semantics for module inclusion
> would not be backwards compatibile imho.

What are "multiple inheritence semantics"?

-- 
Daniel Brockman <daniel / brockman.se>