前記事につづき、プログラミング言語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
になる。
以上です。