# Method overload, care to improve?

**URL:** <https://www.ruby-forum.com/t/method-overload-care-to-improve/84408>\
**Category:** Ruby\
**Created:** [March 21, 2006, 12:48am UTC](https://www.ruby-forum.com/t/method-overload-care-to-improve/84408 "2006-03-21T00:48:52Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [March 21, 2006, 12:48am UTC](https://www.ruby-forum.com/t/method-overload-care-to-improve/84408/1 "2006-03-21T00:48:52Z")

</div>

Have a need to create method overloading, so I put together an  
implementation. Curious what other think of it; how to improve it; or  
do it a better way.

Thanks,  
T.

# ---- overload.rb

class Module

def method\_overloads  
@method\_overloads ||= {}  
end

def overload( name, \*signiture, &block )  
name = name.to\_sym

```
if method_overloads.key?( name )
  method_overloads[name][signiture] = block

else
  method_overloads[name] = {}
  method_overloads[name][signiture] = block

  if method_defined?( name )
    #method_overloads[name][nil] = instance_method( name ) #true
    alias_method( "#{name}Generic", name )
    has_generic = true
  else
    has_generic = false
  end

  define_method( name ) do |*args|
    ovr = self.class.method_overloads[:"#{name}"]
    sig = args.collect{ |a| a.class }
    hit = nil
    faces = ovr.keys.sort { |a,b| b.size <=> a.size }
    faces.each do |cmp|
      next unless cmp.size == sig.size
      cmp.size.times { |i|
        next unless cmp[i] < sig[i]
      }
      hit = cmp
    end

    if hit
      ovr[hit].call(*args)
    else
      if has_generic #ovr[nil]
        send( "#{name}Generic", *args )
        #ovr[nil].bind(self).call(*args)
      else
        raise NoMethodError
      end
    end

  end

end

```

end

end

# \_\_\_\_\_ \_

# |\_ _|_\_ \_\__| |_

# | |/ \_ / \_\_| \_\_|

# | | _/\_ \ |_

# |_|\_ **||** _/\_\_|

# 

class X

def x  
“hello”  
end

overload :x, Integer do |i|  
i  
end

overload :x, String, String do |s1, s2|  
[s1, s2]  
end

end

x = X.new  
p x.x  
p x.x(1)  
p x.x(“a”,“b”)

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [March 21, 2006, 1:04am UTC](https://www.ruby-forum.com/t/method-overload-care-to-improve/84408/2 "2006-03-21T01:04:03Z")

</div>

On 20 Mar 2006 15:46:09 -0800, Trans [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Have a need to create method overloading, so I put together an

IIRC, the ‘strongtyping’ library on RAA provide method overloading  
among other things.

andrew

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [March 21, 2006, 2:33am UTC](https://www.ruby-forum.com/t/method-overload-care-to-improve/84408/3 "2006-03-21T02:33:54Z")

</div>

Thanks Andrew.

I’m afraid I don’t care for how the strongtyping lib handles  
overloading with the #overload call internal to the method. It  
undermines dynamic capabilities. Eg.

```
 def bar(*args)
     overload(args, String, String) {
        | s1, s2 |
        ...
        return
     }

     overload(args, String, Integer) {
        | s, i |
        ...
        return
     }

     overload_error args
  end

```

It would be tricky to add another overload post defnition of the  
original.

T.

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [March 21, 2006, 7:09am UTC](https://www.ruby-forum.com/t/method-overload-care-to-improve/84408/4 "2006-03-21T07:09:00Z")

</div>

Trans wrote:

> ```
> return
> 
> ```
> 
> It would be tricky to add another overload post defnition of the  
> original.

I would agree. You loose the most powerful part - to define methods  
after the  
definition. One good example for multimethods are in event callbacks.  
You can  
capture the event you want without a bunch of switch code:

overload :mouse\_down, LeftButton, ButtonDown do |button, state, x, y|  
puts “left mouse button down”  
end

Unfortunately it looks a bit odd. If I was using it in a library  
internally it  
might be cool. But exposing library users to it would be something  
else. I  
wonder if it could be done like this:

class Test  
generic :foo

def foo.Integer\_String( x, y )  
return x \* y  
end  
end

t = Test.new  
t.foo( 10, 20 )

Here’s a prototype, but doesn’t quite work:

def generic( symbol )  
class\_eval do  
#instance\_variable\_set( “@@#{symbol.to\_s}”, Object.new )  
@@foo = Object.new  
define\_method( symbol ) do | \*args |  
# Find applicable method and call  
@@foo.Integer\_String( \*args )  
end  
end  
end

Mike

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [March 21, 2006, 7:49am UTC](https://www.ruby-forum.com/t/method-overload-care-to-improve/84408/5 "2006-03-21T07:49:08Z")

</div>

Here’s a working prototype:

class Test  
#generic :foo (would generate the code below)  
@@foo = Object.new  
define\_method :foo do |\*args|  
method = args.map { |a| a.class }.join( “\_” )  
@@foo.send( method, \*args )  
end  
end

class Test  
def @@foo.Fixnum\_Fixnum( x, y )  
return x \* y  
end

def @@foo.Fixnum\_Float( x, y )  
return x / y  
end  
end

t = Test.new  
t.foo( 10, 20 )  
t.foo( 10, 2.0 )

It’s inefficient and all that, but I think it looks pretty nice 🙂  
Mike

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [March 21, 2006, 9:09am UTC](https://www.ruby-forum.com/t/method-overload-care-to-improve/84408/6 "2006-03-21T09:09:23Z")

</div>

The “methods” are executed in the context of an Object object,  
instead of in the context of a Test object… And it behaves  
like a singleton… And it doesn’t handle subclasses of a  
Class…

No, I don’t think it’s a usable solution…

The code below would probably work better. It uses the  
monitor-function “def\_overload” which uses Module#wrap\_method  
[1] to add functionality to an already existing method. If the  
arguments of a call matches the fingerprint, the given block  
will be executed, otherwise the previous definition of the same  
method is checked/called.

gegroet,  
Erik V. - [http://www.erikveen.dds.nl/](http://www.erikveen.dds.nl/)

[1] [Ruby Monitor-Functions - Or Meta-Meta-Programming in Ruby](http://www.erikveen.dds.nl/monitorfunctions/index.html)

* * *

require “ev/metameta”

class Module  
def def\_overload(method, \*klasses, &block)  
wrap\_method(method) do |org\_method, args|  
nok =  
args.zip(klasses).find do |a, k|  
if k.kind\_of?(Class)  
not a.kind\_of?(k)  
else  
not a.respond\_to?(k)  
end  
end

```
   if nok
     if org_method
       org_method.call(*args)
     else
       raise NotImplementedError, "Method #{self}##{method} not

```

implemented for arguments #{args.inspect}."  
end  
else  
block.call(\*args)  
end  
end  
end  
end

class Test  
def\_overload(:foo, Fixnum, :to\_f) do |x, y|  
x + y.to\_f  
end

def\_overload(:foo, Fixnum, Fixnum) do |x, y|  
x \* y  
end

def\_overload(:foo, Fixnum, Float) do |x, y|  
x / y  
end  
end

t = Test.new

p t.foo(10, 20)  
p t.foo(10, 2.0)  
p t.foo(10, “2”)  
p t.foo(10, :two) # Should fail…

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [March 21, 2006, 11:03am UTC](https://www.ruby-forum.com/t/method-overload-care-to-improve/84408/7 "2006-03-21T11:03:59Z")

</div>

Points taken for the problems of the implementation, and the metameta  
solution  
is nicely done. However, I would like to see if it’s possible to use  
the ‘def’  
syntax for defining multimethods. Below is a version I have been toying  
with,  
keep in mind the ‘self’ problem still exists and it is very inefficient.  
Is it  
possible to execute a method in a specific context, or is there a way to  
make  
the following work correctly?

class Generic  
def find\_method( args )  
methods(false).sort.reverse.each do |method\_name|  
signature = method\_name.split( “\_” ).map do |i| eval i end  
result = args.zip( signature ).map do |m|  
m[1] == nil ? true : m[0].kind\_of?( m[1] )  
end  
return method\_name if result.inject( true ) { |a, i| a and i }  
end  
raise NotImplementedError  
end  
end

class MultimethodTest  
@@foo = Generic.new

def @@foo.Fixnum( number )  
puts ‘foo( Fixnum )’  
end

def @@foo.String\_Numeric( string, number )  
puts ‘foo( String, Number )’  
end

def foo( \*args )  
@@foo.send( @@foo.find\_method( args ), \*args )  
end  
end

t = MultimethodTest.new  
t.foo( 10 )  
t.foo( “Hello”, 10 )

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [March 21, 2006, 11:39am UTC](https://www.ruby-forum.com/t/method-overload-care-to-improve/84408/8 "2006-03-21T11:39:03Z")

</div>

> Is it possible to execute a method in a specific context,

As long as the objects are of the same class, you could use  
Method#unbind and UnboundMethod#bind. If they aren’t, you could  
experiment with Method#to\_proc.

> @@foo = Generic.new

Why?..

gegroet,  
Erik V. - [http://www.erikveen.dds.nl/](http://www.erikveen.dds.nl/)

* * *

class Foo  
def bar  
self.object\_id  
end  
end

foo1 = Foo.new  
foo2 = Foo.new

p foo1.bar  
p foo2.bar

p foo1.method(:bar).unbind.bind(foo2).call  
p Foo.instance\_method(:bar).bind(foo2).call

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [March 21, 2006, 12:38pm UTC](https://www.ruby-forum.com/t/method-overload-care-to-improve/84408/9 "2006-03-21T12:38:56Z")

</div>

Erik V. wrote:

> > Is it possible to execute a method in a specific context,
> 
> As long as the objects are of the same class, you could use  
> Method#unbind and UnboundMethod#bind. If they aren’t, you could  
> experiment with Method#to\_proc.

Thanks, I’ll give it a try.

> > @@foo = Generic.new
> 
> Why?..

I was trying to keep the class namespace clean and to consolidate the  
methods  
into their own space. The unbind/bind technique is interesting - now I  
tried  
making the generic object the same class, and doing this:

def foo( \*args )  
method = @@foo.method( @@foo.find\_method( args ) )  
method.unbind.bind( self ).call( \*args )  
end

But alas, I get:  
generic.rb:33:in `bind’: singleton method called for a different object  
(TypeError)

I guess I don’t fully understand how singleton methods differ from  
normal  
methods. Thanks for all your time, this is just a curiosity not for a  
project  
per se.
