LoginSignup
2
2

More than 5 years have passed since last update.

Ruby の Method#=== が定義されていないのでつらい問題

Posted at

ブログ記事からの転載です。
Method#=== が定義されていなくてつらい問題です。

Proc#===

Proc オブジェクトでは #call で評価することが出来ますが、そのエイリアスとして #=== が存在します。

upcase = proc { |a| a.upcase }
upcase.call "homu"
# => "HOMU"
upcase === "mami"
# => "MAMI"

これは次のように when で使用出来るようにするためです。

def sign n
    case n
    when proc { |n| 0 < n }
        1
    when proc { |n| 0 > n }
        -1
    else
        0
    end
end

sign -4  # => -1
sign 0   # => 0
sign 7   # => 1

ここで、Ruby に精通してる人なら気づくと思いますが、#method を使って proc { |n| 0 < n }0.method(:<) と書き直したくなります。

def sign n
    case n
    # #method はレシーバのメソッドをブロックオブジェクトとして返す
    when 0.method(:<)
        1
    when 0.method(:>)
        -1
    else
        0
    end
end

しかし、これは上手く動作しません。

なぜなら #method が返す Method クラスでは #=== が定義されていないからです。

Method#=== を定義する gem をつくった

と、いうことで Method#=== を使うことが出来る gem をつくりました。

$ gem install procedureable_method

で、インストールすることが出来ます。

使い方

使い方は

require "procedureable_method"
using ProcedureableMethod

という風に refinements として使用するか

require "procedureable_method/core_ext"

として直接モンキーパッチを適用されるかします。

これで Method#=== を使用する事が出来ます。

require "procedureable_method"

using ProcedureableMethod

def sign n
    case n
    when 0.method(:<)
        1
    when 0.method(:>)
        -1
    else
        0
    end
end

sign -4  # => -1
sign 0   # => 0
sign 7   # => 1

これで無事に whenMethod を渡して評価する事が出来ました。

関係ないですが when の場合はちゃんと refinements で定義したメソッドが呼ばれるんですね。

本体にも Method#=== が追加されてほしい。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2