How does ruby handle overloading?

Matz once replied on Cedric's blog that

I am not against "method overloading", but it very easily leads to
optional static typing in the language, which changes the language
very drastically, since you need to specify "type" to overload
arguments. Without well-thought design, it can "destroy" the language
and its culture. I have not yet got that well-thought design of method
overloading.

This is a very general argument, what concerns me is that if, for
instance, we have Matrix and Graph, and we'd like to be able to draw
both of them (the two 'draw's would have the same semantic but
different implementation logic), how 're we going to be able to
overload draw on Matrix and Graph like what we do in C++ or Java:

void draw(Matrix);
void draw(Graph);

One might argue that 'draw' should actually be a member function of
Matrix and Graph so the problem is moot. But then there's two more
problems:

1. if we can't modify Matrix or Graph, and writing a non-member 'draw'
is the only thing we can do to extend the interface of them, and we
actually can write 'draw' in terms of the public interface of Matrix
and Graph.

2. if '1' doesn't matter (because in ruby we actually can add new
methods to an existing class), then can you please give another more
qualified example?

pongba wrote:

what concerns me is that if, for
instance, we have Matrix and Graph, and we'd like to be able to draw
both of them (the two 'draw's would have the same semantic but
different implementation logic), how 're we going to be able to
overload draw on Matrix and Graph like what we do in C++ or Java:

void draw(Matrix);
void draw(Graph);

def draw(arg)
  if arg.is_a? Matrix
    do_stuff
  elsif arg.is_a? Graph
    do_other_stuff
  end
end

HTH,
Sebastian

···

--
NP: Dream Theater - Honor Thy Father
Jabber: sepp2k@jabber.org
ICQ: 205544826

Hi --

Matz once replied on Cedric's blog that

I am not against "method overloading", but it very easily leads to
optional static typing in the language, which changes the language
very drastically, since you need to specify "type" to overload
arguments. Without well-thought design, it can "destroy" the language
and its culture. I have not yet got that well-thought design of method
overloading.

This is a very general argument, what concerns me is that if, for
instance, we have Matrix and Graph, and we'd like to be able to draw
both of them (the two 'draw's would have the same semantic but
different implementation logic), how 're we going to be able to
overload draw on Matrix and Graph like what we do in C++ or Java:

void draw(Matrix);
void draw(Graph);

One might argue that 'draw' should actually be a member function of
Matrix and Graph so the problem is moot. But then there's two more
problems:

1. if we can't modify Matrix or Graph, and writing a non-member 'draw'
is the only thing we can do to extend the interface of them, and we
actually can write 'draw' in terms of the public interface of Matrix
and Graph.

2. if '1' doesn't matter (because in ruby we actually can add new
methods to an existing class), then can you please give another more
qualified example?

I am a great believer in 'extend'.

module MatrixEnhancements
   def draw
     ....
   end
end
m = Matrix.new.extend(MatrixEnhancements)

This lets you endow specific objects with what they need, and you
don't have to change classes globally. It is, in my opinion, a much
under-utilized technique.

David

···

On Sun, 2 Sep 2007, pongba wrote:

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

This is a very general argument, what concerns me is ...

[snip]

One might argue that [...] so the problem is moot.
But then there's two more problems:

1. if we can't modify Matrix or Graph [...]

2. if '1' doesn't matter (because in ruby we actually can add new
methods to an existing class), then can you please give another more
qualified example?

What I hear you saying is:

  There's a problem with what Matz describes, because...
  OK, wait, that's not a problem.
  But then there's this other problem:
  Er, OK, that's not actually a problem either.
  Can you please show me what the problem is?

I think you've reasoned it out for yourself: there isn't a problem.
Even if it were, the two other responses in this thread show you ways
you could work around it if you needed to (which you don't).

···

On Sep 2, 6:48 am, pongba <pon...@gmail.com> wrote:

Matz once replied on Cedric's blog that

I am not against "method overloading", but it very easily leads to
optional static typing in the language, which changes the language
very drastically, since you need to specify "type" to overload
arguments. Without well-thought design, it can "destroy" the language
and its culture. I have not yet got that well-thought design of method
overloading.

This is a very general argument, what concerns me is that if, for
instance, we have Matrix and Graph, and we'd like to be able to draw
both of them (the two 'draw's would have the same semantic but
different implementation logic), how 're we going to be able to
overload draw on Matrix and Graph like what we do in C++ or Java:

void draw(Matrix);
void draw(Graph);

One might argue that 'draw' should actually be a member function of
Matrix and Graph so the problem is moot. But then there's two more
problems:

1. if we can't modify Matrix or Graph, and writing a non-member 'draw'
is the only thing we can do to extend the interface of them, and we
actually can write 'draw' in terms of the public interface of Matrix
and Graph.

Somehow I miss something in this sentence. You write "if..." but I do not see any "then". So what exactly are you trying to say / ask here?

You can usually change classes. Also, there are numerous ways to implement dispatching on argument types, for example this one:

class Drawer
   @draw = Hash.new(lambda {|x| raise "Cannot draw #{x.inspect}"}).
     merge(Matrix => lambda {|x| puts "Drawing Matrix #{x.inspect}"},
       Graph => lambda {|x| puts "Drawing Graph #{x.inspect}"})

   def draw(obj)
     self.class.instance_eval {@draw}[obj.class][obj]
   end
end

irb(main):012:0> Drawer.new.draw(Matrix.new)
Drawing Matrix #<Matrix:0x7ff62e38>
=> nil
irb(main):013:0> Drawer.new.draw(Graph.new)
Drawing Graph #<Graph:0x7ff5fe54>
=> nil
irb(main):014:0> Drawer.new.draw("foo")
RuntimeError: Cannot draw "foo"
         from (irb):4
         from (irb):9:in `'
         from (irb):9:in `draw'
         from (irb):14
irb(main):015:0>

There are others, you can find some of them in the Ruby Garden Wiki (which seems to be unavailable ATM).

2. if '1' doesn't matter (because in ruby we actually can add new
methods to an existing class), then can you please give another more
qualified example?

Example for what?

Kind regards

  robert

···

On 02.09.2007 14:48, pongba wrote:
         from :0

There is a very good reading for support overloading, regardless. By
separating code based on interface it is much easier to override a
method. Without that one usually has to consider all the possible
interfaces in every override --even though one may only be interested
in a single one. OTOH, the downside of overriding is interface
collision --if more than one interface match, which method gets the
call? So it's actually easier to manage without it. And one can easily
work around the interface limitation by defining separate methods for
each case and having the main method as a simple dispatcher.

T.

···

On Sep 2, 5:50 am, pongba <pon...@gmail.com> wrote:

Matz once replied on Cedric's blog that

I am not against "method overloading", but it very easily leads to
optional static typing in the language, which changes the language
very drastically, since you need to specify "type" to overload
arguments. Without well-thought design, it can "destroy" the language
and its culture. I have not yet got that well-thought design of method
overloading.

This is a very general argument, what concerns me is that if, for
instance, we have Matrix and Graph, and we'd like to be able to draw
both of them (the two 'draw's would have the same semantic but
different implementation logic), how 're we going to be able to
overload draw on Matrix and Graph like what we do in C++ or Java:

void draw(Matrix);
void draw(Graph);

One might argue that 'draw' should actually be a member function of
Matrix and Graph so the problem is moot. But then there's two more
problems:

1. if we can't modify Matrix or Graph, and writing a non-member 'draw'
is the only thing we can do to extend the interface of them, and we
actually can write 'draw' in terms of the public interface of Matrix
and Graph.

Just FYI, I developed one a long time ago, based on Euphoria's model.
Basically worked like this, You define a "type" as such:

    type :foo, SomeClass, Modules, ..., :methods, ... do |v|
      # validation block ...
    end

Such that type "foo" is a subclass of SomeClass and/or includes
Modules, and/or repsonds_to? :methods, and/or validates against the
given block.

You'd then use this type definition to validate:

  def x(v)
    foo!(v)
    ...
  end

Of course, ideally then you could do:

  def x(foo v)
    ...
  end

Seems to me that's about the best one could do with a Ruby overload
system. Question is, is it worth the overhead?

T.

···

On Sep 2, 5:50 am, pongba <pon...@gmail.com> wrote:

Matz once replied on Cedric's blog that

I am not against "method overloading", but it very easily leads to
optional static typing in the language, which changes the language
very drastically, since you need to specify "type" to overload
arguments. Without well-thought design, it can "destroy" the language
and its culture. I have not yet got that well-thought design of method
overloading.

But isn't type-switch generally believed to be a bad thing?

···

On Sep 2, 9:25 pm, Sebastian Hungerecker <sep...@googlemail.com> wrote:

pongba wrote:
> what concerns me is that if, for
> instance, we have Matrix and Graph, and we'd like to be able to draw
> both of them (the two 'draw's would have the same semantic but
> different implementation logic), how 're we going to be able to
> overload draw on Matrix and Graph like what we do in C++ or Java:

> void draw(Matrix);
> void draw(Graph);

def draw(arg)
  if arg.is_a? Matrix
    do_stuff
  elsif arg.is_a? Graph
    do_other_stuff
  end
end

HTH,
Sebastian
--
NP: Dream Theater - Honor Thy Father
Jabber: sep...@jabber.org
ICQ: 205544826

lol
Basically you're right.
What I wanted was an example that can only be solved with overloading,
but then there's the ultimate type-switch trick, so.. :stuck_out_tongue:

···

On Sep 2, 10:34 pm, Phrogz <phr...@mac.com> wrote:

On Sep 2, 6:48 am, pongba <pon...@gmail.com> wrote:

> This is a very general argument, what concerns me is ...
[snip]
> One might argue that [...] so the problem is moot.
> But then there's two more problems:

> 1. if we can't modify Matrix or Graph [...]

> 2. if '1' doesn't matter (because in ruby we actually can add new
> methods to an existing class), then can you please give another more
> qualified example?

What I hear you saying is:

  There's a problem with what Matz describes, because...
  OK, wait, that's not a problem.
  But then there's this other problem:
  Er, OK, that's not actually a problem either.
  Can you please show me what the problem is?

I think you've reasoned it out for yourself: there isn't a problem.
Even if it were, the two other responses in this thread show you ways
you could work around it if you needed to (which you don't).

Sorry, I meant 'what if' :slight_smile:
There're lots of ways to implement them, among which the more
automatic one is the StrongType module. But they all rely on explicit
dynamic type-switch, which isn't as clear as the "traditional"
overloading mechanism(i.e. draw(Matrix); draw(Graph); ).
I don't whether there're other problem related to this approach since
I'm a ruby-newbie.

···

On Sep 3, 12:26 am, Robert Klemme <shortcut...@googlemail.com> wrote:

On 02.09.2007 14:48, pongba wrote:

> Matz once replied on Cedric's blog that

> I am not against "method overloading", but it very easily leads to
> optional static typing in the language, which changes the language
> very drastically, since you need to specify "type" to overload
> arguments. Without well-thought design, it can "destroy" the language
> and its culture. I have not yet got that well-thought design of method
> overloading.

> This is a very general argument, what concerns me is that if, for
> instance, we have Matrix and Graph, and we'd like to be able to draw
> both of them (the two 'draw's would have the same semantic but
> different implementation logic), how 're we going to be able to
> overload draw on Matrix and Graph like what we do in C++ or Java:

> void draw(Matrix);
> void draw(Graph);

> One might argue that 'draw' should actually be a member function of
> Matrix and Graph so the problem is moot. But then there's two more
> problems:

> 1. if we can't modify Matrix or Graph, and writing a non-member 'draw'
> is the only thing we can do to extend the interface of them, and we
> actually can write 'draw' in terms of the public interface of Matrix
> and Graph.

Somehow I miss something in this sentence. You write "if..." but I do
not see any "then". So what exactly are you trying to say / ask here?

You can usually change classes. Also, there are numerous ways to
implement dispatching on argument types, for example this one:

class Drawer
   @draw = Hash.new(lambda {|x| raise "Cannot draw #{x.inspect}"}).
     merge(Matrix => lambda {|x| puts "Drawing Matrix #{x.inspect}"},
       Graph => lambda {|x| puts "Drawing Graph #{x.inspect}"})

   def draw(obj)
     self.class.instance_eval {@draw}[obj.class][obj]
   end
end

irb(main):012:0> Drawer.new.draw(Matrix.new)
Drawing Matrix #<Matrix:0x7ff62e38>
=> nil
irb(main):013:0> Drawer.new.draw(Graph.new)
Drawing Graph #<Graph:0x7ff5fe54>
=> nil
irb(main):014:0> Drawer.new.draw("foo")
RuntimeError: Cannot draw "foo"
         from (irb):4
         from (irb):9:in `'
         from (irb):9:in `draw'
         from (irb):14
         from :0
irb(main):015:0>

There are others, you can find some of them in the Ruby Garden Wiki
(which seems to be unavailable ATM).

> 2. if '1' doesn't matter (because in ruby we actually can add new
> methods to an existing class), then can you please give another more
> qualified example?

Example for what?

Kind regards

        robert

Hi --

···

On Mon, 3 Sep 2007, pongba wrote:

On Sep 2, 9:25 pm, Sebastian Hungerecker <sep...@googlemail.com> > wrote:

pongba wrote:

what concerns me is that if, for
instance, we have Matrix and Graph, and we'd like to be able to draw
both of them (the two 'draw's would have the same semantic but
different implementation logic), how 're we going to be able to
overload draw on Matrix and Graph like what we do in C++ or Java:

void draw(Matrix);
void draw(Graph);

def draw(arg)
  if arg.is_a? Matrix
    do_stuff
  elsif arg.is_a? Graph
    do_other_stuff
  end
end

HTH,
Sebastian
--
NP: Dream Theater - Honor Thy Father
Jabber: sep...@jabber.org
ICQ: 205544826

But isn't type-switch generally believed to be a bad thing?

It's actually class-switch (type and class aren't the same in Ruby),
and it's an expedient that can be useful in some situations but tends
to interfere with "thinking in Ruby", so to speak. Ruby generally is
more about objects and their capabilities, and less about which
classes happened to spawn them.

David

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

If you read Matz's statement (which you quoted) again you'll find the reason why there is not that kind of overloading you are looking for. :slight_smile:

  robert

···

On 03.09.2007 03:36, pongba wrote:

On Sep 3, 12:26 am, Robert Klemme <shortcut...@googlemail.com> wrote:

On 02.09.2007 14:48, pongba wrote:

Matz once replied on Cedric's blog that
I am not against "method overloading", but it very easily leads to
optional static typing in the language, which changes the language
very drastically, since you need to specify "type" to overload
arguments. Without well-thought design, it can "destroy" the language
and its culture. I have not yet got that well-thought design of method
overloading.
This is a very general argument, what concerns me is that if, for
instance, we have Matrix and Graph, and we'd like to be able to draw
both of them (the two 'draw's would have the same semantic but
different implementation logic), how 're we going to be able to
overload draw on Matrix and Graph like what we do in C++ or Java:
void draw(Matrix);
void draw(Graph);
One might argue that 'draw' should actually be a member function of
Matrix and Graph so the problem is moot. But then there's two more
problems:
1. if we can't modify Matrix or Graph, and writing a non-member 'draw'
is the only thing we can do to extend the interface of them, and we
actually can write 'draw' in terms of the public interface of Matrix
and Graph.

Somehow I miss something in this sentence. You write "if..." but I do
not see any "then". So what exactly are you trying to say / ask here?

You can usually change classes. Also, there are numerous ways to
implement dispatching on argument types, for example this one:

class Drawer
   @draw = Hash.new(lambda {|x| raise "Cannot draw #{x.inspect}"}).
     merge(Matrix => lambda {|x| puts "Drawing Matrix #{x.inspect}"},
       Graph => lambda {|x| puts "Drawing Graph #{x.inspect}"})

   def draw(obj)
     self.class.instance_eval {@draw}[obj.class][obj]
   end
end

irb(main):012:0> Drawer.new.draw(Matrix.new)
Drawing Matrix #<Matrix:0x7ff62e38>
=> nil
irb(main):013:0> Drawer.new.draw(Graph.new)
Drawing Graph #<Graph:0x7ff5fe54>
=> nil
irb(main):014:0> Drawer.new.draw("foo")
RuntimeError: Cannot draw "foo"
         from (irb):4
         from (irb):9:in `'
         from (irb):9:in `draw'
         from (irb):14
         from :0
irb(main):015:0>

There are others, you can find some of them in the Ruby Garden Wiki
(which seems to be unavailable ATM).

2. if '1' doesn't matter (because in ruby we actually can add new
methods to an existing class), then can you please give another more
qualified example?

Example for what?

Kind regards

        robert

Sorry, I meant 'what if' :slight_smile:
There're lots of ways to implement them, among which the more
automatic one is the StrongType module. But they all rely on explicit
dynamic type-switch, which isn't as clear as the "traditional"
overloading mechanism(i.e. draw(Matrix); draw(Graph); ).
I don't whether there're other problem related to this approach since
I'm a ruby-newbie.

Thanks, David. That helps :slight_smile:

···

On Sep 3, 10:23 am, dbl...@wobblini.net wrote:

Hi --

On Mon, 3 Sep 2007, pongba wrote:
> On Sep 2, 9:25 pm, Sebastian Hungerecker <sep...@googlemail.com> > > wrote:
>> pongba wrote:
>>> what concerns me is that if, for
>>> instance, we have Matrix and Graph, and we'd like to be able to draw
>>> both of them (the two 'draw's would have the same semantic but
>>> different implementation logic), how 're we going to be able to
>>> overload draw on Matrix and Graph like what we do in C++ or Java:

>>> void draw(Matrix);
>>> void draw(Graph);

>> def draw(arg)
>> if arg.is_a? Matrix
>> do_stuff
>> elsif arg.is_a? Graph
>> do_other_stuff
>> end
>> end

>> HTH,
>> Sebastian
>> --
>> NP: Dream Theater - Honor Thy Father
>> Jabber: sep...@jabber.org
>> ICQ: 205544826

> But isn't type-switch generally believed to be a bad thing?

It's actually class-switch (type and class aren't the same in Ruby),
and it's an expedient that can be useful in some situations but tends
to interfere with "thinking in Ruby", so to speak. Ruby generally is
more about objects and their capabilities, and less about which
classes happened to spawn them.

David

--
* Books:
   RAILS ROUTING (new!http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)