What's so special about operators, built-in classes and modules?

I just noticed this little quirk. Is there something
I am doing wrong?

  module Mod
    def *(other)
      puts "#{self} * #{other}"
    end
  end

  class String
    include Mod
  end

  "ff" * 5 #=> nothing

But, if I add the method explicitly instead of through a module I get:

  class String
    #include Mod
    def *(other)
      puts "#{self} * #{other}"
    end
  end

  "ff" * 5 #=> "ff" * 5

This seems to be a quirk (bug?) and only happens when mixing modules,
built in classes (like Array) and operator methods.

Mixing in a module works fine with the combinations:
   Non built-in class, operators
   Built-in class, non operator method

···

--
Jim Freeze

[...]

module Mod
  def f; :f;end
end

class A;
end
class A;
  include Mod
end
A.new.f # => :f

class B
  def f; :g;end
end
class B
  include Mod
end
B.new.f # => :g

class B
  def f; :f;end
end
B.new.f # => :f

String.method_defined?(:*) # => true

···

On 2005-07-26 07:43:29 +0900, Jim Freeze wrote:

--
Florian Frank

* Florian Frank <flori@nixe.ping.de> [2005-07-26 08:26:21 +0900]:

class B
  def f; :g;end
end
class B
  include Mod
end
B.new.f # => :g

Thanks Forian. For some reason I always thought that including a mod
would shadow old methods.
I suppose for my method to work (no pun intended), the standard
operating procedure is to:

  class B
    alias :_orig_f
    remove_method :f
    include Mod
  end

I'm a little slow in getting around to these types of things, I'm
surprised I haven't seen an RCR to reduce this to a single line.

···

--
Jim Freeze

You can use Ruby to do most of the work:

module Mod
  def f; :"new-f"; end
  def self.included(o)
    instance_methods(false).each do |m|
      o.instance_eval do
        alias_method("_orig_#{m}", m)
        remove_method(m)
      end
    end
    super
  end
end

class A
  def f; :f; end
end

A.new.f # => :f

class A
  include Mod
end

A.new._orig_f # => :f
A.new.f # => :"new-f"

···

On 2005-07-26 21:48:34 +0900, Jim Freeze wrote:

I'm a little slow in getting around to these types of things, I'm
surprised I haven't seen an RCR to reduce this to a single line.

--
Florian Frank

Jim Freeze wrote:

* Florian Frank <flori@nixe.ping.de> [2005-07-26 08:26:21 +0900]:

class B
def f; :g;end
end
class B
include Mod
end
B.new.f # => :g

Thanks Forian. For some reason I always thought that including a mod
would shadow old methods.
I suppose for my method to work (no pun intended), the standard
operating procedure is to:

  class B
    alias :_orig_f
    remove_method :f
    include Mod
  end

I'm a little slow in getting around to these types of things, I'm
surprised I haven't seen an RCR to reduce this to a single line.

Including a module is just like inheriting from a class--the module is
above you in the ancestor list. I guess the intuitive meaning of
"include" might be different--one might think it meant "define all
methods from the module at this point in my class definition". Maybe
"inherit <module>" would be a better name for the construct...

So would the RCR be for a construct that inserted a module between each
instance of B and B itself?

One week and five days ago,

Joe Van Dyk <joevandyk@gmail.com> writes:

I thought that the methods and constants in a module were
just inserted into a class.

Daniel Brockman <daniel@brockman.se> writes:

Yet another reason why modules and classes should
be unified.

Austin Ziegler <halostatue@gmail.com> writes:

I don't see it, personally. I really don't see why they
should be unified in the least.

Twelve hours ago,

Jim Freeze <jim@freeze.org> writes:

For some reason I always thought that including a mod
would shadow old methods.

Dear Austin,

While the superficial and cosmetic difference between these
two almost completely equivalent concepts continue to
mislead users, do you still not see “in the least” any
reason whatsoever to unify them?

Oh, and before someone comes shouting “but classes can be
instantiated and modules can't,” let me just post this:

   class Module
     def new(*a, &b)
       const_defined?(:Viagra) or
         const_set(:Viagra, Class.new.include(self))
       const_get(:Viagra).new(*a, &b)
     end
   end

···

--
Daniel Brockman <daniel@brockman.se>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.

* Joel VanderWerf <vjoel@path.berkeley.edu> [2005-07-27 04:52:29 +0900]:

> Thanks Forian. For some reason I always thought that including a mod
> would shadow old methods.
> I suppose for my method to work (no pun intended), the standard
> operating procedure is to:
>
> class B
> alias :_orig_f
> remove_method :f
> include Mod
> end
>
Including a module is just like inheriting from a class--the module is
above you in the ancestor list. I guess the intuitive meaning of
"include" might be different--one might think it meant "define all
methods from the module at this point in my class definition". Maybe
"inherit <module>" would be a better name for the construct...

My simple thought process was always thinking that 'include'ing a Module
was the same as writing the methods myself. So

  class A
    def m
      puts "A#m"
    end
    def m
      puts :m
    end
  end
  A.new.m #=> :m

was the same thing as

  module Mod
    def m
      puts :m
    end
  end
  class A
    def m
      puts "A#m"
    end
    include Mod
  end
  A.new.m #=> :m

So, I thought it was redefining the method and the old method
was being lost if it did not have an alias.

But, as you say, it is more like inheritance.

So would the RCR be for a construct that inserted a module between each
instance of B and B itself?

Would be nice if the notation was external to the class
since there is no difference between:

  class A
    include Mod
    def m; puts "A#m"; end
  end

and

  class A
    def m; puts "A#m"; end
    include Mod
  end

···

--
Jim Freeze

Joe Van Dyk <joevandyk@gmail.com> writes:
> I thought that the methods and constants in a module were
> just inserted into a class.

Daniel Brockman <daniel@brockman.se> writes:
> Yet another reason why modules and classes should
> be unified.

Austin Ziegler <halostatue@gmail.com> writes:
> I don't see it, personally. I really don't see why they
> should be unified in the least.

Twelve hours ago,
Jim Freeze <jim@freeze.org> writes:
> For some reason I always thought that including a mod
> would shadow old methods.

Dear Austin,

While the superficial and cosmetic difference between these
two almost completely equivalent concepts continue to
mislead users, do you still not see "in the least" any
reason whatsoever to unify them?

Nope. I'll note that others have argued better in favour of this than
you have and they're still not unified. I think that unification would
increase the confusion far MORE than what is currently present.

Oh, and before someone comes shouting "but classes can be
instantiated and modules can't," let me just post this:

   class Module
     def new(*a, &b)
       const_defined?(:Viagra) or
         const_set(:Viagra, Class.new.include(self))
       const_get(:Viagra).new(*a, &b)
     end
   end

That's not instantiating a module. It's cute, but it's not
instantiating a module.

-austin

···

On 7/26/05, Daniel Brockman <daniel@brockman.se> wrote:
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Austin Ziegler <halostatue@gmail.com> writes:

While the superficial and cosmetic difference between
these two almost completely equivalent concepts continue
to mislead users, do you still not see "in the least" any
reason whatsoever to unify them?

Nope.

Then I'm forced to conclude that you are shying away from
the truth, as it is staring you in the face.

I'll note that others have argued better in favour
of this than you have and they're still not unified.

That's a new one — argument by pointing out that there are
better arguments in favor of the opposing side.

I think that unification would increase the confusion far
MORE than what is currently present.

That is a reasonable belief. Indeed, I'm not completely
sure myself that unification would reduce net confusion.
So I'd be interested in seeing some arguments.

Here is an example of an argument:

Whenever you bring up the issue of modules vs. classes,
there will generally be at least one person who believes
that including a module is the same as copying its body.
This confusion would go away if the two were unified.

   class Module
     def new(*a, &b)
       const_defined?(:Viagra) or
         const_set(:Viagra, Class.new.include(self))
       const_get(:Viagra).new(*a, &b)
     end
   end

That's not instantiating a module. It's cute, but it's not
instantiating a module.

Of course it's not instantiating a module, but it's pretty
much _as good as_ instantiating a module. It lets you use
modules instead of classes, which demonstrates that the
distinction is superficial.

···

--
Daniel Brockman <daniel@brockman.se>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.

That is a reasonable belief. Indeed, I'm not completely sure myself that
unification would reduce net confusion. So I'd be interested in seeing some
arguments.

well - classes can't do this

   module MainHelper
     ...
   end

   module SetupMain
     include MainHelper
     def run
       ...
     end
   end

   module QueryMain
     include MainHelper
     def run
       ...
     end
   end

   module BackupMain
     include MainHelper
     def run
       ...
     end
   end

   class Main
     def main
       table = {
         SETUP => SetupMain,
         QUERY => QueryMain,
         BACKUP => BackupMain,
       }
       modul = table[ mode ]
       extend modul
       run
     end
   end

this sort of aggregation can be very nice for source management when classes
are growing large - one can simply make the class be what it needs to be and
nothing more. in short - classes do not support ad hoc aggreation, which is
very nice feature to give up.

Here is an example of an argument:

Whenever you bring up the issue of modules vs. classes,
there will generally be at least one person who believes
that including a module is the same as copying its body.
This confusion would go away if the two were unified.

this is a similar 'argument':

   in c most people think that a definition like

     int foobar (const char * string);

   will prevent people from modifiying string. it won't. for that one needs

     int foobar (const char * const string);

   why not unify them?

the answer is obvious: because they are differnet. a focus on clarifying
doccumentation might be wiser in this case. and, in the end, certain people
are simply going to have to be told to rtfm - not everything can be intuitive
AND powerful.

That's not instantiating a module. It's cute, but it's not
instantiating a module.

Of course it's not instantiating a module, but it's pretty
much _as good as_ instantiating a module. It lets you use
modules instead of classes, which demonstrates that the
distinction is superficial.

does it?

   harp:~ > cat a.rb
   class Module
     def new(*a, &b)
       (@__klass__ ||= (m = self and Class::new{ include m }))::new(*a, &b)
     end
   end

   module M
     class << self
       def class_method
         42
       end
     end
     def instance_method
       42
     end
   end

   m = M::new
   p m.instance_method
   p m.class.class_method

   harp:~ > ruby a.rb
   42
   a.rb:21: undefined method `class_method' for #<Class:0xb75d0480> (NoMethodError)

and, of course, you still can't inherit from M - but i realize this needed be
so.

i think i'm with austin on this one.

cheers.

-a

···

On Thu, 28 Jul 2005, Daniel Brockman wrote:
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

Austin Ziegler <halostatue@gmail.com> writes:

While the superficial and cosmetic difference between these two
almost completely equivalent concepts continue to mislead users,
do you still not see "in the least" any reason whatsoever to
unify them?

Nope.

Then I'm forced to conclude that you are shying away from the
truth, as it is staring you in the face.

I'm not forcing you, either directly or indirectly (by my position).

I don't see any reason to unify the concepts behind classes and
modules. I see plenty of reasons to *not* do it (and Ara has
illustrated one). I see plenty of reasons to *improve* the
documentation and explanations surrounding modules and how they
work, but none of these are an indication that the unification of
classes and modules is a good idea in the least.

I'm not shying away from the truth; I'm just rejecting your
position. There *is* a difference, you know.

I'll note that others have argued better in favour of this than
you have and they're still not unified.

That's a new one — argument by pointing out that there are
better arguments in favor of the opposing side.

I'm not quite sure how you see that. 1) There *are* better arguments
(with strong theoretical backing) for unification than what you've
said to date. Look for Mathieu's arguments on ruby-core. 2) Matz has
still indicated that he's unconvinced. Therefore, 3) you have to do
a much better job of arguing this case than Mathieu has done to
convince Matz.

If Matz is convinced, then I will also be convinced that the
unification won't introduce more problems than it supposedly solves.

I think that unification would increase the confusion far MORE
than what is currently present.

That is a reasonable belief. Indeed, I'm not completely
sure myself that unification would reduce net confusion.
So I'd be interested in seeing some arguments.

I believe that unification would increase net confusion. Modules as
mixins are a simple, clean way of doing MI without hobbling oneself
the way that Java has done with Interfaces. If you have an
alternative that doesn't lead down the path to the nightmare of C++
MI, I'd love to hear it. Additionally, if modules and classes are
the same, then the existence of two keywords -- which will be
necessary for historical reasons -- will itself introduce confusion.

Here is an example of an argument:

Whenever you bring up the issue of modules vs. classes, there will
generally be at least one person who believes that including a
module is the same as copying its body. This confusion would go
away if the two were unified.

Would it? I don't think so. It would seem to me that the confusion
of:

  module Mod
  end

  class Foo
    include Mod
  end

would not be reduced with:

  class Mod
  end

  class Foo
    include Mod
  end

At least as far as "include" is concerned.

class Module
  def new(*a, &b)
    const_defined?(:Viagra) or
    const_set(:Viagra, Class.new.include(self))
    const_get(:Viagra).new(*a, &b)
  end
end

That's not instantiating a module. It's cute, but it's not
instantiating a module.

Of course it's not instantiating a module, but it's pretty
much _as good as_ instantiating a module. It lets you use
modules instead of classes, which demonstrates that the
distinction is superficial.

Maybe you use modules differently, but while you can do something
like that, I still don't think that the difference between the two
is simply a missing "new". Note that you're getting an automatic
allocator and initializer in Class, but there's no allocators for
Module objects.

-austin

···

On 7/27/05, Daniel Brockman <daniel@brockman.se> wrote:
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

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

That is a reasonable belief. Indeed, I'm not completely
sure myself that unification would reduce net confusion.
So I'd be interested in seeing some arguments.

well - classes can't [extend objects] [...]

Is that an argument in favor of unifying them?

Here is an example of an argument:

Whenever you bring up the issue of modules vs. classes,
there will generally be at least one person who believes
that including a module is the same as copying its body.
This confusion would go away if the two were unified.

this is a similar 'argument':

   in c most people think that a definition like

     int foobar (const char * string);

   will prevent people from modifiying string. it won't.
   for that one needs

     int foobar (const char * const string);

   why not unify them?

the answer is obvious: because they are differnet.

I agree. My point is that Ruby's classes and modules are
very much alike. If ‘const char *’ and ‘const char * const’
were very much alike, I'd be in favor of unifying them.
But since the two pointer types are not alike at all, your
analogy doesn't apply.

I'm talking about two very similar concepts that are
commonly mistaken for very different concepts, while you are
talking about two very different concepts that are commonly
mistaken for equal concepts. Do you see the difference?

a focus on clarifying doccumentation might be wiser in
this case.

Documentation in always nice, but I'm afraid the quality of
the documentation is irrelevant to the discussion at hand.

and, in the end, certain people are simply going to have
to be told to rtfm

Granted.

not everything can be intuitive AND powerful.

But realize that what I'm saying is that Ruby is *not* more
powerful with classes and modules separate than it would be
with them unified. I'm saying that Ruby would be equally
powerful (nay, more powerful) after the unification.

Would it be more intuitive? I think so.

···

--
Daniel Brockman <daniel@brockman.se>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.

Hmm, for some reason this part of your message was left out
of my reply buffer, so I forgot to reply to it!

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

That's not instantiating a module. It's cute, but it's
not instantiating a module.

Of course it's not instantiating a module, but it's
pretty much _as good as_ instantiating a module. It lets
you use modules instead of classes, which demonstrates
that the distinction is superficial.

does it?

[Complicated way of saying module.new.class != module.]

As I trust you are already aware, that's easily fixed:
Just redefine the ‘class’ method to return the module.

and, of course, you still can't inherit from M - but i
realize this needed be so.

Yes, you can:

   module N
     include M
   end

···

--
Daniel Brockman <daniel@brockman.se>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.

Actually, the first example will prevent people from modifying the string, at least directly. Adding the second const only prevents them from reassigning the "string" variable within the function.

The biggest problem here is that in C strings don't exist. People go to great lengths to pretend that they do, but really, they don't. There are only arrays of characters terminated by a null character. If people would quit believing that strings actually exist, then the problems with strings and C would go away.

What makes the problem worse is that C makes it really easy to believe that strings exist. Having constructs like "Hello World!\n" makes people think that there is such a thing as a string, but the compiler sees that as being identical to {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\n', '\0'}.

Now you could argue that strings actually *do* exist, and that they *are* arrays of characters terminated by a null. I don't buy it though. Why not? Because *anything* can be a string of characters terminated by a null. C may be statically typed, but try declaring an array of characters and then calling strlen(the_array). It may give you a length, or maybe a segfault, but it will never say "hey! that's not a string!"

Aside from the issue of C strings, I'd say the way const is used in functions is b0rken in C. Take int foo(const int bar); Since bar is passed by value, any modifications of it in the body of the function are only local to the function. In my experience good C coders treat every parameter passed by value as "const", otherwise they lose a record of what parameters the function was supplied. Because of this, "const" is only really useful when applied to pointers. And the syntax for that is really confusing -- generally the syntax for pointers is really confusing in C as a general rule. The concept of a pointer is pretty simple -- it's an address in memory, the only thing that makes it difficult is the syntax.

In this bit of code, you can change the variable a, which is a pointer, making it point at something else, but you can't change the value it points at. As for b, you can change the value it points at, but you can't change the variable itself.

int bar(const int *a, int *const b, const int c)
{
     int d, e;
     //*a = 3;
     *b = 4;
     a = &d;
     //b = &e;
     //c = 5;
}

The "const char* string" works the same way, preventing you from modifying the contents of the string, but letting you reassign the variable. The way to read it (I believe) is "if you dereference 'string' you will get a constant character".

Anyhow, bringing this back to Ruby...

I think Modules and Classes should be separate, but I think there's a lot of confusion there.

Classes are pretty straightforward, but modules are not. I'd say most of the confusion comes from the fact that modules can either be groups of functions that are mixed in to other things, or they can be namespaces. That dual use gets confusing. Oh, and it's also confusing that a Class is a Module in the inheritance tree.

I agree that it's confusing that including a module doesn't hide functions that a class defines on its own. IMHO it isn't clear that "include FooModule" is similar to inheritance. It looks like it's similar to "attr_accessor", not like class Foo < Bar.

Adding documentation would help a bit with this issue, but it doesn't seem like the ideal approach to me. Instead of documenting a confusing issue, why not understand why it's confusing and fix it?

I'd suggest that for one thing, modules-as-namespaces should disappear, there should simply be a "namespace" keyword so "Math::PI" is in the Math namespace, not the Math module. Then, I'd say "mixin" instead of "module". Finally to address the issue of it not overriding methods that already exist, maybe a second parameter to "include" named "override" that defaults to false? Sure, that could break things when you mix something in that clobbers a "helper method", but just having that option there makes people realize that it doesn't always override things.

As for multiple inheritance vs. single inheritance, I think the problem isn't a technical one, it's a human one. As Adam P Jenkins pointed out:

   By your logic, C++ and Python don't have the diamond problem either. Both
   of those languages have well defined ways in which the method to call is
   chosen, which have to do with the order in which the programmer writes things.

So the question becomes "What is going to provide the most flexibility with the least confusion?" I think that rules out multiple inheritance. Ruby is a really flexible language. Even without resorting to "eval" you can do some pretty astounding things. But in general the approach seems to be "unless you're trying to do something tricky, things generally behave as they should". I would say that having multiple inheritance adds a lot of potential for confusion without a lot of benefit. Crafty programmers can get all(?) the benefits of MI from Ruby today, as long as they're willing to be sneaky about it. Less crafty programmers don't have to worry about the diamond problem. Doesn't that seem like the way things should be?

Ben

···

On Jul 27, 2005, at 12:07, Ara.T.Howard wrote:

this is a similar 'argument':

  in c most people think that a definition like

    int foobar (const char * string);

  will prevent people from modifiying string. it won't. for that one needs

    int foobar (const char * const string);

  why not unify them?

the answer is obvious: because they are differnet. a focus on clarifying
doccumentation might be wiser in this case. and, in the end, certain people
are simply going to have to be told to rtfm - not everything can be intuitive
AND powerful.

Hmm, for some reason this part of your message was left out
of my reply buffer, so I forgot to reply to it!

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

That's not instantiating a module. It's cute, but it's
not instantiating a module.

Of course it's not instantiating a module, but it's
pretty much _as good as_ instantiating a module. It lets
you use modules instead of classes, which demonstrates
that the distinction is superficial.

does it?

[Complicated way of saying module.new.class != module.]

As I trust you are already aware, that's easily fixed:
Just redefine the ‘class’ method to return the module.

yes - just pointing out there's more to being a class than having a new
method...

and, of course, you still can't inherit from M - but i
realize this needed be so.

Yes, you can:

  module N
    include M
  end

the problem is a bit deeper than that and stem from the fact that including a
module does not inject the included modules singleton methods into the
'includee'. for example (note this has the fix suggested above):

   harp:~ > cat a.rb
   class Module
     def new(*a, &b)
       (@__klass__ ||= (m = self and Class::new{ include(@@m = m); def class;@@m;end }))::new(*a, &b)
     end
   end
   module M
     class << self
       def class_method
         42
       end
     end
     def instance_method
       42
     end
   end

   module N
     include M
   end

   begin
     m = M::new
     p m.class
     p m.instance_method
     p m.class.class_method
   rescue => e
     puts "#{ e.message } (#{ e.class }"
   end

   begin
     n = N::new
     p n.class
     p n.instance_method
     p n.class.class_method
   rescue => e
     puts "#{ e.message } (#{ e.class }"
   end

   harp:~ > ruby a.rb
   M
   42
   N
   42
   undefined method `class_method' for N:Module (NoMethodError

i'm not saying it's not possible - just that it's a bit more work than you're
suggesting. doing things consistently at an object, class, module, and
singleton_class level gets very confusing very quicky - just check out the code
for my traits lib to see just how. :wink:

i personally often get around this detail by

   module M
     module ClassMethods
     end
     module InstanceMethods
     end
     include InstanceMethods
     self.extend ClassMethods
     def self::included other
       class << other
         include InstanceMethods
       end
       other.extend ClassMethods
     end
   end

or something similar - in otherwords factor out class methods so that can be
added individually to other classes/modules when they are included there.
thus begins the trickiness...

(ps. for some reason the charset from your message is very odd - it may be on
my end but thought you might like to know. it looks like some sort of escape
chars around '@' signs - coloring?)

cheers.

-a

···

On Thu, 28 Jul 2005, Daniel Brockman wrote:
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

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

That is a reasonable belief. Indeed, I'm not completely
sure myself that unification would reduce net confusion.
So I'd be interested in seeing some arguments.

well - classes can't [extend objects] [...]

Is that an argument in favor of unifying them?

i don't think so. the reason is that if classes could extend objects we'd
have a real issue with ancestors/inheritence. what i mean is that if one
could

   class A
   end
   class B
     include A
   end

and this were the 'same' as

   class B < A
   end

then that __would__ be confusing since including multiple classes would imply
multiple inheritence. if it did not imply multiple inheritence would the only
difference be that one (B < A) made b.is_a?(A) true while the other (B.include
A) did not - even though, for all intents and purposes they could do all the
same things. this seems broken and confusing either way - tough i'll admit
the idea is interesting...

I agree. My point is that Ruby's classes and modules are
very much alike.

execept - and this is important - wrt inheritence.

were very much alike, I'd be in favor of unifying them.
But since the two pointer types are not alike at all, your
analogy doesn't apply.

and i'm saying they are not that much alike because on this crucial
difference.

Documentation in always nice, but I'm afraid the quality of
the documentation is irrelevant to the discussion at hand.

requiring people to understand the language fully, regardless of what that
takes, before attempting to change it is never really irrelevant is it?

and, in the end, certain people are simply going to have
to be told to rtfm

Granted.

not everything can be intuitive AND powerful.

But realize that what I'm saying is that Ruby is *not* more
powerful with classes and modules separate than it would be
with them unified. I'm saying that Ruby would be equally
powerful (nay, more powerful) after the unification.

well - if you can work out how inheritence would work out - then maybe.
realize that i'm one of those people that think that normal hackers cannot
handle multiple inheritence anyhow and that, at the very least, it's an idea
far less powerfull than mixins.

cheers.

-a

···

On Thu, 28 Jul 2005, Daniel Brockman wrote:
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

Hi,

···

In message "Re: What's so special about operators, built-in classes and modules?" on Thu, 28 Jul 2005 01:42:39 +0900, Daniel Brockman <daniel@brockman.se> writes:

well - classes can't [extend objects] [...]

Is that an argument in favor of unifying them?

Then you will have complex network of classes instead of simple tree
structure, sharing code with modules. That makes things much complex,
without buying you anything except for the feeling of being more generic.

              matz.

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

and, of course, you still can't inherit from M - but i
realize this needed be so.

Yes, you can:

  module N
    include M
  end

the problem is a bit deeper than that and stem from the
fact that including a module does not inject the included
modules singleton methods into the 'includee'.

Right, but to me that is just another reason to unify.
How is this inconsistency a feature? Why is it not fixed?

Does any code depend on the fact that including a module
does not pull in its singleton methods?

(This deserves a thread of its own, and in fact probably
already has at least one. I'll search the archives later.)

[snipped nice example code]

i'm not saying it's not possible - just that it's a bit
more work than you're suggesting. doing things
consistently at an object, class, module, and
singleton_class level gets very confusing very quicky -
just check out the code for my traits lib to see just how.
:wink:

i personally often get around this detail by

   module M
     module ClassMethods
     end
     module InstanceMethods
     end
     include InstanceMethods
     self.extend ClassMethods
     def self::included other
       class << other
         include InstanceMethods
       end
       other.extend ClassMethods
     end
   end

or something similar - in otherwords factor out class
methods so that can be added individually to other
classes/modules when they are included there. thus begins
the trickiness...

Yes, I use similar hacks too. But don't you agree that it
would be nicer if modules and classes were consistent in
this regard, rendering these hacks unnecessary?

(I realize that I'm shifting the discussion instead of
meeting your arguments.)

(ps. for some reason the charset from your message is very
odd - it may be on my end but thought you might like to
know. it looks like some sort of escape chars around '@'
signs - coloring?)

Hmm... sounds weird. I do tend to use Unicode characters,
specifically quotation marks. How does this look?

                  ‘foo’ “bar”

It's supposed to be the word foo in single quotes followed
by the word bar in double quotes.

···

--
Daniel Brockman <daniel@brockman.se>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.

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

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

That is a reasonable belief. Indeed, I'm not completely
sure myself that unification would reduce net confusion.
So I'd be interested in seeing some arguments.

well - classes can't [extend objects] [...]

Is that an argument in favor of unifying them?

i don't think so. the reason is that if classes could
extend objects we'd have a real issue with
ancestors/inheritence. what i mean is that if one could

   class A
   end
   class B
     include A
   end

and this were the 'same' as

   class B < A
   end

then that __would__ be confusing since including multiple
classes would imply multiple inheritence.

And how is that confusing? It's exactly what currently
happens when you include multiple modules.

   module A ; end
   module B ; end

   class C
     include A
     include B
   end

   C.new.is_a? A #=> true
   C.new.is_a? B #=> true

if it did not imply multiple inheritence would the only
difference be that one (B < A) made b.is_a?(A) true while
the other (B.include A) did not -

I don't see how this could ever make sense.

even though, for all intents and purposes they could do
all the same things. this seems broken and confusing
either way - tough i'll admit the idea is interesting...

The version that doesn't have B.include(A) imply b.is_a?(A)
does seem broken and confusing, but is a straw man.

I agree. My point is that Ruby's classes and modules are
very much alike.

execept - and this is important - wrt inheritence.

How so?

were very much alike, I'd be in favor of unifying them.
But since the two pointer types are not alike at all,
your analogy doesn't apply.

and i'm saying they are not that much alike because on
this crucial difference.

See above.

Documentation in always nice, but I'm afraid the quality
of the documentation is irrelevant to the discussion
at hand.

requiring people to understand the language fully,
regardless of what that takes, before attempting to change
it is never really irrelevant is it?

If anything I said in this thread was out of ignorance, I
apologize for my arrogance. However, I would appreciate it
if you would point any such errors out.

not everything can be intuitive AND powerful.

But realize that what I'm saying is that Ruby is *not*
more powerful with classes and modules separate than it
would be with them unified. I'm saying that Ruby would
be equally powerful (nay, more powerful) after
the unification.

well - if you can work out how inheritence would work out
- then maybe.

But inheritance would work exactly the same as it does now.

realize that i'm one of those people that think that
normal hackers cannot handle multiple inheritence anyhow
and that, at the very least, it's an idea far less
powerfull than mixins.

How is multiple inheritance far less powerful than mixins?

(I actually consider Ruby's mixins to *be* a kind of
multiple inheritance, but I'll play along for a while.)

···

On Thu, 28 Jul 2005, Daniel Brockman wrote:

--
Daniel Brockman <daniel@brockman.se>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.

Very nice technique, but...

Ara.T.Howard wrote:

  module M
    module ClassMethods
    end
    module InstanceMethods
    end
    include InstanceMethods
    self.extend ClassMethods
    def self::included other
      class << other
        include InstanceMethods

          ^^^^^^^^^^^^^^^^^^^^^^^
This is redundant.

      end
      other.extend ClassMethods
    end
  end

For the newbies: In the old, old days (1.6 maybe), we had to use
#append_features instead of #included, and that did require explicitly
including the module. And sometimes we had to whack it with a dinosaur
bone to make it work.

Btw, the doc for append_features is unclear (as someone else on this
thread pointed out) about the difference between including a module and
adding methods:

------------------------------------------------- Module#append_features
     append_features(mod) => mod

···

------------------------------------------------------------------------
     When this module is included in another, Ruby calls
     +append_features+ in this module, passing it the receiving module
     in _mod_. Ruby's default implementation is to add the constants,
     methods, and module variables of this module to _mod_ if this
     module has not already been added to _mod_ or one of its ancestors.
     See also +Module#include+.