How does ruby handle overloading?

P

pongba

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?
 
S

Sebastian Hungerecker

pongba said:
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
 
D

dblack

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

--
* 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)
 
P

Phrogz

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).
 
R

Robert Klemme

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
 
T

Trans

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.

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.
 
P

pongba

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

HTH,
Sebastian

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

pongba

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).

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.. :p
 
P

pongba

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' :)
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.
 
D

dblack

Hi --

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)
 
P

pongba

Hi --






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)

Thanks, David. That helps :)
 
R

Robert Klemme

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' :)
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.

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. :)

robert
 
T

Trans

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.

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top