pockestrap

Programmer's memo

Rubyで型情報を使ってオーバーロードをする

以前Rubyでoverloadをするという記事を書きました。 この記事で紹介しているoverloader gemを使うとRubyオーバーロードができるようになります。

overloader gemは今まで引数の数の違いでしかオーバーロードを定義できませんでしたが、v0.2.0で型情報を使用してオーバーロードを定義できるようにしたので、改めて紹介しようと思います。

Installation

まず、型の機能を使うにはRuby 2.7以上を使う必要があります。 そしてruby-signature gemを別途インストールする必要があります。 ruby-signatureは記事執筆時点ではまだRubyGems.orgにpublishされていないので、git cloneしてインストールしてください。

$ git clone https://github.com/ruby/ruby-signature
$ bundle install
$ bundle exec rake install

そしてoverloader gemも忘れずにインストールしましょう。こちらはRubyGems.orgからインストールできます。

$ gem install overloader

Usage

メソッド定義の前の行にそのメソッドの型情報をコメントで書くと、その型情報を使ってオーバーロードが定義されます。

require 'overloader'
require 'overloader/type'

class A
  extend Overloader
  overload do
    # (String, Integer) -> untyped
    def foo(x, y) 'str int' end

    # (Integer, String) -> untyped
    def foo(x, y) 'int str' end

    # (Symbol, Symbol) -> untyped
    def foo(x, y) 'sym sym' end
  end
end

a = A.new
p a.foo('bar', 42) # => "str int"
p a.foo(42, 'baz') # => "int str"
p a.foo(:a, :b)    # => "sym sym"
p a.foo(:a, 42)    # => ArgumentError

この通り、各メソッド呼び出しの引数の型によって呼ばれるメソッドが振り分けられるようになっています。 そして型が合わない引数を渡した場合にはArgumentErrorが出るようになっています。

Implementation

ruby-signature自体のテストに使われている、実行時に型検査を行う仕組みをそのまま流用しています。

メソッドに渡されてきた引数をコメントで書いた型定義と突き合わせて、型に合う引数が渡っていたら該当のメソッドを呼び、でなければ次の型を検証する、と言った実装になっています。

overloader gemではむずかしいことはしていないので、興味がある方はぜひコードを読んでみてください。 https://github.com/pocke/overloader/blob/v0.2.0/lib/overloader/type/checker.rb