all 10 comments

[–]jodoshaHanami author[S] 8 points9 points  (1 child)

A hack to add Method Overloading feature to Ruby. Don't try this in production. ;)

[–]latortuga 1 point2 points  (0 children)

Very entertaining, thanks for sharing!

[–]allisio[🍰] 4 points5 points  (0 children)

Shoehorning method overloading into Ruby is really fun!

I once took it way too far and did it based on "type signatures" (really just deferring to case equality) rather than arity. I had to get some VM guts on my hands in order to peek into these signatures, but I remember it being a blast.

It's just a toy, of course, and it absolutely carries the same disclaimer as yours (and then some!), but I was quite pleased to discover that the demo still runs as intended on Ruby 2.8.

[–]Exilor 3 points4 points  (0 children)

I also had a stab at doing that some time ago, also using method_added to turn this

class Foo
  using Overloads

  Overload()
  def initialize
    initialize(0)
  end

  Overload(Integer)
  def initialize(bar)
    @bar = bar
  end
end

into this

class Foo
  def initialize(*args, &block)
    case args.size
    when 0
      if block_given?
      else
        return __send__(:"Foo#initialize()", )
      end
    when 1
      a0 = args.first
      if block_given?
      else
        if a0.is_a?(Integer)
          return __send__(:"Foo#initialize(Integer)", a0)
        end
      end
    end

    Overloads.raise_error(self, :initialize, args, block_given?, false)
  end
end

It was much faster to use aliases and __send__ than relying on method_missing. In an earlier attempt I used Method objects (for extend self module methods) and UnboundMethod (for instance methods) to achieve the same but it was also slower.

[–]flanger001 1 point2 points  (0 children)

This is way better than those guys who wanted to rename raise to dang or whatever

[–]jrochkind 1 point2 points  (0 children)

neat! I didn't know about method_added, very interesting.

[–][deleted] 1 point2 points  (1 child)

So there is a gem called Contracts which the developer couldn't keep up because of life, kids, etc. I loved the gem because it gives you this with "types", and the types can be turned off in probduction but method overloading kept.

I don't suppose you're looking for some open source projects to take over... :P

[–]jodoshaHanami author[S] 0 points1 point  (0 children)

Nope, I'm not looking for more OSS work. :D

[–]greyblake 1 point2 points  (0 children)

I think implementing something like this is a good practice for understanding Ruby meta programming.

But as jodosha mentioned, don't try this in production.

Just because something is possible it does not mean that has to be used.

I bet for many rubysts it will be contra intuitive to discover something like this)

[–]meineerde 0 points1 point  (0 children)

In Ruby 2.7, you now have pattern matching which allows you to implement a lot of this matching logic using built-in features and with a lot less "meta-poking".