2010年1月9日土曜日

【On Lisp】5 Returning Functions

ひさしぶりに、のんびりLisp。


** 5 Returning Functions

*** 5.1
- そうか、レキシカルスコープでは関数の呼出し時に新
しいクロージャをつくることができるということは、
ダイナミック変数とは違う意味で動的であるといえ
るな。
- ダイナミック変数でも関数呼出し時に関数を作ること
はできるが、それはどこまでいっても単なるダイナミッ
クバインディングなだけではある。

- 例

CL-USER> (defun make-adder (n)
#'(lambda (x)
(+ x n)))
MAKE-ADDER
CL-USER> (setq add3 (make-adder 3))
#<Interpreted Closure (:INTERNAL MAKE-ADDER) @ #x1000ee3a82>
CL-USER> (funcall add3 2)
5
CL-USER> (proclaim '(special m))
T
CL-USER> (setq m 1)
1
CL-USER> (defun make-adder-dyn (m)
#'(lambda (x)
(+ x m)))
MAKE-ADDER-DYN
CL-USER> (setq add3-dyn (make-adder-dyn 3))
#<Interpreted Closure (:INTERNAL MAKE-ADDER-DYN) @ #x100112ead2>
CL-USER> (funcall add3-dyn 2)
3
CL-USER> (setq m 2)
2
CL-USER> (funcall add3-dyn 2)
4
CL-USER> (setq n 2)
2
CL-USER> (funcall add3 2)
5
CL-USER>

- そうか。関数を引数にとり関数を返す関数が意味をも
つのは、返している関数が単なる関数ではなく、レキ
シカルクロージャであり、引数である関数をクローズ
しているからなんだな。
- クロージャの威力の紹介として、オブジェクトシステ
ムなど、値の保持方法として紹介されることが多い。
それはそれで役に立つけれども、そもそもOOをあまり
やらないという人にはいまいち説得力がないように思
う。でも、汎関数プログラミングのインフラだよ、と
言われれば誰にとっても説得力があるように思う。

*** 5.2
- 直交性という観点にいくなら、それはもうSchemeの
独壇場のような。。。
- おお、Common LispのScheme化的な動きが、、、

*** 5.4
- PGのcomposeはPAIPのものよりもいい。

- PAIPのは、1引数関数しか合成できない。

(defun compose (&rest functions)
#'(lambda (x)
(reduce #'funcall functions :from-end t :initial-value x)))

*** 5.5
- なるほど。再帰のパターン化というのはこんな感じな
んだな。
- やはりlambdaというのは、実行遅延なんだよなぁ。

CL-USER> (setq x 3)
3
CL-USER> x
3
CL-USER> (setq hoge #'(lambda () (setq x 5)))
#<Interpreted Function (unnamed) @ #x1000ff6d62>
CL-USER> x
3
CL-USER> (funcall hoge)
5
CL-USER> x
5
CL-USER>

- thunkも実行遅延なんだけど、より原始的な意味でい
うと、サブルーチンというか手続きというかもそれ自体
実行遅延だよね。
- 関数もそれらの一種とするなら、関数と関数呼出しと
は制御構造の親玉だよね。コードを切り貼りして実行
タイミングを調整する機構。本質的にはgotoやjump
だし。すると、構造化プログラミングとの折り合いは
どうなっているのだろう?
- このあたりについて、プログラミング言語階層での説
明語彙として「継続」を位置づけるのはどうだろう?
継続という用語の導入として、継続を取り出してファー
ストクラスで扱うときが始めてということが多いけど、
それだと逆にわかりにくいのではないか?
- 例えば末尾再帰もある意味継続の構造の問題ですよね。
継続にノイズが入らないのが末尾再帰というか。
- 関数が数学的な意味での関数であるとすると、話はまっ
たく別になるな。そもそも実行順とか制御の考えが入っ
て無いから。
- なんかつれづれなるままに、だな。。。

- さて、遅延させて渡すときはthunkを作る(使う)など
して、 関数でもコードの抽象化(パターン抽出)ができ
るよ、というのがこの章のテーマのようだ。
- ただし、やってみるとわかるが、関数だけで抽象化
させようとすると、関数的抽象化がどうできるのか
にいろいろ腐心することになる。
- もっと手軽に抽象化するなら、関数的抽象化ではな
く表現的抽象化であり、それがこの本の主題たるマ
クロなんですよ〜、ということかなぁ。

こつこつ。

0 件のコメント: