How to realize method/function overloading in Ruby?

I think Function Overloading in C++ is very meaningful. And currently
the case for me is: How I can make use of method/function overloading
in Ruby?
Besides you might tell me Ruby is designed to exclude method
overloading, can you tell me sth more for the Overloading purpose?

Shiwei Z. wrote:

I think Function Overloading in C++ is very meaningful. And currently
the case for me is: How I can make use of method/function overloading
in Ruby?

Can you provide us with a few real-world cases where you would want to
use method overloading in C++? In Ruby, duck-typing does away with some
of those cases, and we can show you how.

If you show us what you are wanting to do, that makes it easier to
discuss the best ways to do it. (Unless, of course, you’re just trying
to accomplish a checkmark in a feature list.)

On 15.01.2007 12:38, Shiwei Z. wrote:

I think Function Overloading in C++ is very meaningful. And currently
the case for me is: How I can make use of method/function overloading
in Ruby?

You can find a page linked from this Wiki page - currently our network
is shady so I cannot post the proper link:

Besides you might tell me Ruby is designed to exclude method
overloading, can you tell me sth more for the Overloading purpose?

I am not sure what exactly you mean by this.

Kind regards

robert

I think Function Overloading in C++ is very meaningful. And
> currently
> the case for me is: How I can make use of method/function
> overloading
> in Ruby?
> Besides you might tell me Ruby is designed to exclude method
> overloading, can you tell me sth more for the Overloading purpose?

There are quite a few thread on overloading around here, but I’ll make a short summary (once for all, hopefully ?). C++ overloading has basically two purposes:

1) get around strict typing limitations (a function working on numbers might want to work on int, float, double…)
2) provide defalt values (though it is not really overloading, it really looks like it).

In my opinion, any other way to use overloading (that is, a function doing something completely different when called with (int, double) than with (double) is characteristic of bad programming practices).

Ruby provides solutions for both cases:

1) you don’t need to declare type for a ruby function, so you can call one unique function with many different types. If you need to separate some cases depending on the type of one of the argument, try something like:

case argument
when String
do something with the string
when Array

end

The best approach to this is probably ‘duck typing’, that is: you don’t care what objects the function is fed to, as long as the behave correctly (they have the right methods that do something appropriate)

2) ruby provides default arguments as well (more powerful than C++):

irb(main):004:0> def m(a, b = 0, c = a)
irb(main):005:1> [a,b,c]
irb(main):006:1> end
=> nil
irb(main):007:0> m(1)
=> [1, 0, 1]
irb(main):008:0>

Does that answer your question, or you know some other uses of overloading I didn’t mention ?

Cheers,

Vince

Phrogz wrote:

use method overloading in C++? In Ruby, duck-typing does away with some
of those cases, and we can show you how.

If you show us what you are wanting to do, that makes it easier to
discuss the best ways to do it. (Unless, of course, you’re just trying
to accomplish a checkmark in a feature list.)

        Thanks. My requirement is: I've had a method "logon(uid,

pswd, conn = nil, privilege = nil)", but I want to add another method
like “logon(easyconn)”, where easyconn is in the format of
“uid/pswd@host:port/service_name [AS {SYSOPER|SYSDBA}]” . I think I have
3 solutions to implement this:
S1) Keep the existing method “logon(uid, pswd, conn = nil, privilege =
nil)” unchanged, and add the method “logon(easyconn)” which will invoke
“logon(uid, pswd, conn = nil, privilege = nil)”.
S2) Refactor the method “logon(uid, pswd, conn = nil, privilege = nil)”,
modify the body of this method in order that it can support the the
format of “uid/pswd@host:port/service_name [AS {SYSOPER|SYSDBA}]”. This
solution is duck-typing.
S3) Keep the existing method “logon(uid, pswd, conn = nil, privilege =
nil)” unchanged, and add another method “logon1(easyconn)” which will
invoke “logon(uid, pswd, conn = nil, privilege = nil)”. Note: logon1 is
a different name with logon.
The method “logon(uid, pswd, conn = nil, privilege = nil)”
has been a certified/tested mothod, and many applications have been
based on it. I am used to thinking of S1), because it doesn’t need
regression test for the existing method “logon(uid, pswd, conn = nil,
privilege = nil)”. However, Ruby doesn’t support method overloading, so
I have to discard S1) and choose S3). But S3) seems not a good
impression for users, because the new name “logon1” is not consist with
the existing name “logon”. The inconsistence might make users confused I
think.So I want to apply S2), but it needs regression test, which is a
burden.

Thanks & Best Rgds,
Shiwei

On 1/15/07, [email protected] [email protected] wrote:

overloading is based on knowing the static types of the actual
end
do_something({1,2}) # as Hash version
This is a lot of work when the programmer can achieve the same goal
end
end
def do_something_with_hash(h)

assume h is a hash

end
def do_something_with_int(i)

assume i is an int

end

def do_something(a)
send(“do_something_with_#{a.class.name.downcase}”
end

Shiwei Z. ha escrito:

I think Function Overloading in C++ is very meaningful.

It isn’t.

My requirement is: I’ve had a method “logon(uid,pswd, conn = nil, privilege = nil)”, but I want to add > another method like “logon(easyconn)”, where easyconn is in the format of
“uid/pswd@host:port/service_name [AS {SYSOPER|SYSDBA}]”

Ruby is such a complex language compared to C++ :slight_smile:

class A
private

def _logon( uid, pwd, conn, privilege )
p uid, pwd, conn, privilege
end

public

def logon( uid, pwd = nil, conn = nil, privilege = nil )
if pwd == nil
# parse uid as “uid/pswd@host:port/service_name [AS
{SYSOPER|SYSDBA}]”
# and extract other vars.
uid =~ /(\S+)/(\S+)@(\S+:\S+)(?:\s+AS\s+(SYSOPER|SYSDBA))?/
uid, pwd, conn, privilege = $1, $2, $3, $4
end
_logon(uid, pwd, conn, privilege )
end

end

user cannot see private method _logon

p A.instance_methods.grep /logon/

a = A.new
a.logon( ‘gga’, ‘crap’, ‘host:2322’)
a.logon( ‘gga/crap@host:2322’)
a.logon( ‘gga/crap@host:2322 AS SYSOPER’)

On 1/16/07, Gregory B. [email protected] wrote:

end
Jeez! Sorry for the 3 emails, I must be tired. This is the little
hack I was trying to demonstrate:

seltzer:~/devel/parser-experiment/pegleg_evaluator sandal$ irb

def foo_array(a)
a + [1]
end
=> nil
def foo_string(a)
a << “apple”
end
=> nil
def foo(a)
send(“#{a.class.name.downcase”,a)
end
def foo(a)
send(“foo_#{a.class.name.downcase}”,a)
end
=> nil
foo([1,2,3])
=> [1, 2, 3, 1]
foo(“banana”)
=> “bananaapple”

Though as others mentioned, a lot of this can be avoided by clever
design. :slight_smile:

On Jan 15, 2007, at 6:38 AM, Shiwei Z. wrote:

I think Function Overloading in C++ is very meaningful. And
currently the case for me is: How I can make use of method/
function overloading in Ruby?
Besides you might tell me Ruby is designed to exclude method
overloading, can you tell me sth more for the Overloading purpose?

This is a common question. The short answer is that function
overloading is based on knowing the static types of the actual
arguments to a method and in Ruby the entire notion of ‘static types
of the actual arguments’ is pretty much non-existent.

The longer answer is that for Ruby to provide some sort of
overloading a new syntax for method definition would be required and
then the method lookup algorithm would have to be updated. Warning:
pseudo code ahead.

def do_something( a as Array)
#…
end

def do_something( a as Hash)
#…
end

def do_something(a)
#…
end

do_something([1,2]) # as Array version
do_something({1,2}) # as Hash version
do_something(1) # unspecified version

This would really complicate the method dispatch mechanism as the
class of every argument would have to be examined each time any
method is called. I used literal arrays, hashes, and integers in the
example but in general they would
just be arbitrary expressions. In any case some sort of algorithm
would have to be run each time a method was called. This would
drastically increase method call overhead in Ruby.

This is a lot of work when the programmer can achieve the same goal
with the existing language quite concisely:

def do_something(a)
case a
when Array
# work with array
when Hash
# work with hash
else
# assume integer
end
end

Same effect, no language changes, and the algorithm is explicit and
flexible rather than implicit and rigid.

There is yet another approach. Define different methods for
different arguments:

def do_something_with_array(a)
# assume a is an array
end
def do_something_with_hash(h)

assume h is a hash

end
def do_something_with_int(i)

assume i is an int

end

do_something_with_array([1,2])
do_something_with_hash({1,2})
do_something_with_int(3)

This is of course doing by hand what static overloading does
‘automatically’. In Ruby you still end up doing regular method
lookup for do_something_with_array and company.

The bottom line is that Ruby already provides several methods to deal
with complex argument lists. Adding some sort of class declarations
to formal arguments goes against the grain of Ruby’s design with
little if any benefit to outweigh
the added complexity.

P.S. I seem to remember that there was a considerable amount of
criticism in the C++ community about static function overloading vs.
dynamic dispatch. I’m not sure what the situation is today.

Gary W.

On 1/16/07, Gregory B. [email protected] wrote: