takafumi blog

日々の勉強メモ

【Ruby】 引数の型チェック gem contracts

環境   ruby 2.2.3 CentOS7.0

Rubyを始めてみた。

さて、初めてすぐ気になった事。

関数は以下のように書くわけで

  1 def gcd(a, b)
  2   if b == 0
  3     return a
  4   else
  5     return gcd(b, a % b)
  6   end
  7 end
  8
  9 p gcd(10, 'a')


$ ruby gcd.rb
gcd.rb:9:in `%': String can't be coerced into Fixnum (TypeError)
        from gcd.rb:9:in `gcd'
        from gcd.rb:13:in `<main>'

引数の型チェックがない!

最近はScalaHaskellと静的型付けばかりだったので、とても気になる。
という事で調べると、やっぱり結構気にする人がいるわけで。

fukaoi.org

こちらを参考にcontractsを使ってみる。

$ gem install contracts


  1 require 'contracts'
  2 include Contracts
  3
  4 Contract Num, Num => Num
  5 def gcd(a, b)
  6   if b == 0
  7     return a
  8   else
  9     return gcd(b, a % b)
 10   end
 11 end
 12
 13 p gcd(10, 'a')


$ ruby gcd.rb
/root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/contracts-0.12.0/lib/contracts.rb:48:in `block in <class:Contract>': Contract violation for argument 2 of 2: (ParamContractError)
        Expected: Num,
        Actual: "a"
        Value guarded in: Object::gcd
        With Contract: Num, Num => Num
        At: gcd.rb:5
        from /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/contracts-0.12.0/lib/contracts.rb:154:in `call'
        from /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/contracts-0.12.0/lib/contracts.rb:154:in `failure_callback'
        from /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/contracts-0.12.0/lib/contracts/method_handler.rb:143:in `rescue in block in redefine_method'
        from /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/contracts-0.12.0/lib/contracts/method_handler.rb:136:in `block in redefine_method'
        from gcd.rb:13:in `<main>'

となる。
静的型付けの言語と違い、シンタックスチェック(ruby -cとか)の際にわかるわけではないが、これで想定外の型が間違って通過する事は無くなる。

ただ全てに型チェックを入れると、ダックタイピングがほとんど使えなくなるの注意。

Scalaみたいなダックタイピングができればいんだが。。。 mtoyoshi.hateblo.jp