読者です 読者をやめる 読者になる 読者になる

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

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#=== が追加されてほしい。