LoginSignup
0

More than 5 years have passed since last update.

オブジェクトのインスタンス(または特異)メソッドを取得する[ ]と、特異メソッドを設定する[ ]= をシンボルに定義してみる。(読書メモ)

Last updated at Posted at 2017-02-11

 前記事につづき、プログラミング言語Ruby を読んでいる中で、覚えておきたいと思った、(ややトリッキーな)コードです。
 以下は、同著6.8 関数プログラミング の節の最後に出てきたものに若干手を加えたもので、Symbolクラスに[],[]= 演算子を追加して、オブジェクトの特異メソッドを取得、設定するものです。(なお、実行はruby 2.2 で試しています。)

class Symbol

  def [](o)
    o.method(self)
  end

  def []=(o,f)
    sym = self
    eigenclass = (class << o; self; end)
    eigenclass.instance_eval do
      define_method(sym, f)
    end
  end

end

こうしておいて

str = '='

puts :*[str][10]

とすると、'=' が10個連続した文字列、

==========

が表示される
次に、[]=を使って、

:*[str] = lambda {|n|
    ret = ''
    n.times {|i|
        ret += (self + (i < n-1 ? '|':''))
    }
    ret
}

としてから、再度

puts :*[str][10]

とすると、10個の'='の間に、'|'が挿入されて、

=|=|=|=|=|=|=|=|=|=

が表示される。

さらに、上記のSymbol への[]に加えて、Methodクラスに数学的な意味での関数 f,gの合成

(f・g)(x) ≡ f(g(x))

に相当するアスタリスク演算子 * を以下のように定義する。

class Method
  def *(f)
    if self.respond_to?(:arity) && self.arity  == 1
      lambda {|*args| self.call(f[*args])}
    else
      lambda {|*args| self.call(* f[*args])}
    end
  end
end

上記のSymbolとMethodを使うと

(:*[2]*:+[3])[4]

は、「3を足してから2を掛ける」という関数に 4 を渡す、すなわち

2 * (3 + 4)

と同じで、結果は 14 になる。

以上です。

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
0