ええと、まず目的として、クイックソートなんだから当然再帰を使いたい、
ってのがあって、つまりいかにしてquick_sort_sub()を呼び出すかが
問題なわけですが、
以下の箇所で定義されているふたつのクロージャを、それぞれ
c1, c2とすると、
fp_op2(closure(quick_sort_sub) { ←c1
return closure(left, right) { ←c2
c2が、通常のクイックソートの実行部ですが、その中では、
その外周のクロージャであるc1の引数である、quick_sort_sub()が
参照できるわけですね。
c1は、引数としてクロージャを受け取り、戻り値としてc2を返すわけですが、
c1の引数にc2を渡して実行できれば万事解決である、と。
で、これを実現しているのがfp_op2()であるわけですが、
これは以下のように書き換えることが可能で、
function fp_op2(f) {
c3 = closure(p) {
return p(p);
};
c4 = closure(x) {
c5 = closure(g, h) { return f(x(x))(g, h); };
return c5;
};
return c3(c4);
}
最後のreturnでc3が実行されていますが、
c3というのは、クロージャを受け取り、そのクロージャにそれ自身を
渡して実行して返す関数なわけで、で、c3のpに実際に渡されているのは
c4なので、つまりこのタイミングでc4が実行される。
c4は引数としてxを受け取りますが、c3の定義からして、
xにはc4自身が格納されている。
そして、c4は、戻り値としてc5を返す。
この戻り値は、c3の戻り値でありすなわちfp_op2()の戻り値でもある。
呼び出し元のquick_sort()関数のほうでは、fp_op2()の戻り値に
引数ふたつ与えて評価して、それがクイックソートの実行となる。
で、そのc5ですが、「f(x(x))」のfはつまりc1であり、
その引数の「x(x)」におけるxはc4なので、fの引数には
c4の戻り値が渡されることになる。
c4の戻り値であるc5はつまり、引数をふたつとってc1の戻り値
すなわちc2を実行して返す、という、c2のラッパーなので、
当初の目的である
「c1の引数にc2を渡して実行できれば万事解決である」
というのが実現できている…
うーん、ぶすぶす… (頭から煙が出ている音)
Paul Grahamの「簡潔さは力なり」の中で、
http://www.shiro.dreamhost.com/scheme/trans/power-j.html
数式を散文で書くと量が増える、なんてことが書いてありますが、
数式の力を持ち合わせていない私が書くとこうなってしまうわけで、
やっぱり勉強不足ですね。