12:41:18 [g000013'in]
12:41:53 <g000013> Successful Lisp / David B. Lamkins を読む 11章から再開したいと思います
12:41:59 <g000013> ((( Chapter 11 - Destructive Modification )))
12:42:18 <g000013> これまで破壊的変更はあまり扱ってない感じでしたが、ここで扱うようです
12:44:25 <g000013> 代入と束縛だと代入を多用する方がわかりづらいプログラムを書きやすい的な立場のようです
12:44:27 <g000013> (((( Simple assignment is destructive modification ))))
12:46:50 <g000013> setq/setfでの代入はシンプルな例で、新しい値を確保したメモリの場所に破壊的に書き込むと
12:48:14 <g000013> まあ、そうでしょうねという気はしますが。
12:48:38 <g000013> 前の値を書き換えてしまうので、安易に代入を使うことに対しては慎重になれ、ということなのかもしれません
12:48:48 <g000013> (((( The risk of assignment ))))
12:58:43 <g000013> 代入でのはまりどころという感じですが、
12:59:25 <g000013> まず、自由変数と代入の説明がざっとあって、次にこれの有用な例として
12:59:43 <g000013> よくあるクロージャーでのカウンターの例を挙げています
13:00:38 <g000013> 今度は、別の例で、繰り返し構文での、繰り返し変数が、破壊的に変更される、ということはどういうことかの説明があります
13:01:03 <g000013> これも、クロージャーと組み合せたりすると、割とはまるところかもしれません
13:01:33 <g000013> それで、その次に、Common Lispでの関数の引数の扱いについて触れられていて、
13:04:59 <g000013> いや、ちょっと違いました
13:05:05 <g000013> ここでは、リストのような参照するもの扱う場合に良くある問題で
13:05:52 <g000013> 不用意に破壊的代入をすると、オリジナルのリストを破壊してしまう問題が説明されています
13:08:01 <g000013> 作者のアドバイスとしては、こういう参照的なデータを引数で受け取って(破壊的に)扱うのはやめて
13:08:46 <g000013> 多値で受け渡しする、ということらしいです
13:10:10 <g000013> リストのような容器を使うと、こういう問題があるので、容器を使わないような受け渡しとなるとたしかに多値かなという気はします。
13:10:53 <g000013> (((( Changing vs. copying: an issue of efficiency ))))
13:13:00 <g000013> 色々代入の問題を挙げてきましたが、じゃあなんで扱いづらい「代入」というものが存在するのかということについての説明があります
13:14:25 <g000013> 束縛(毎度別のメモリを確保する)に比べて効率が良いという点と、共有データの表現方法としては直截的であるという説明があります
13:15:06 <g000013> 最近、関数型言語の話題が多いので、良く耳にするトピックかなとは思います
13:15:15 <g000013> (((( Modifying lists with destructive functions ))))
13:16:06 <g000013> ここで、破壊的変更をする関数と、非破壊系の一覧があります
13:16:47 <g000013> append vs nconc を例に説明
13:16:56 <g000013> (((( RPLACA, RPLACD, SETF ...; circularity ))))
13:18:31 <g000013> ここで、コンスセルの説明と、コンスセルの頭と尾をくつけると循環リストが作られることの説明があります
13:18:49 <g000013> (((( Places vs. values: destructive functions don't always have the desired side-effect ))))
13:20:38 <g000013> ここで、これまたはまりどころですが、破壊的な関数に対して、破壊すること(副作用)を期待してはいけない、ということの説明があります
13:21:41 <g000013> 基本的に、返り値を生成するために、破壊しているので、副作用をメインに考えてはいけないというところですね
13:22:12 <g000013> 最も効率が良ければ、一切破壊しない場合もあり得えるというところです
13:22:48 <g000013> (((( Contrast e.g. PUSH and DELETE ))))
13:23:12 <g000013> 副作用を目当てにしてはいけないものの代表例として、deleteがあるのですが、
13:23:34 <g000013> まずは、これの説明のあと、
13:24:21 <g000013> ややこしいですが、副作用も使うというpushの説明があります
13:26:36 <g000013> pushはリストにオブジェクトを先頭にプッシュしていきますが、プッシュされたリストは破壊的に変更されます
13:26:51 <g000013> この挙動が期待できないとpushは有用でないので、pushは副作用の方が大事というところですね。pushの返り値は、破壊的に変更された状態のリストです
13:27:03 <g000013> (((( Shared and constant data: Dangers of destructive changes ))))
13:27:43 <g000013> 今度は定数の破壊についてです。
13:28:08 <g000013> クォートされた '(1 2 3 4)のようなものも定数といいますが、
13:28:38 <g000013> 定数は変更されないことを前提として共有されていることが多いので
13:28:57 <g000013> これが破壊されると、他で共有されているところに妙な影響が出てしまったりします
13:29:50 <g000013> 基本的に、クォートが付いたリストにpushしたりdeleteしたりはしないというのが作法かなとは思います。
13:30:30 <g000013> マクロの式の組み立てなどで、これをやってしまうと、謎のコードが展開されることになったりもします
13:31:18 <g000013> というところで、11章は終わりです
13:31:32 <g000013> 結構はまりどころの説明としては詳しく丁寧かなと思いました
13:32:24 <g000013> 確かに破壊的変更は、色々はまりどころがあるかなと思います
13:32:42 <g000013> この辺りの資料としては、
13:32:44 <g000013> http://tips.lisp-users.org/common-lisp/index.cgi?Scheme%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%8CCommon%20Lisp%E3%81%A7%E3%83%8F%E3%83%9E%E3%82%8A%E3%81%9D%E3%81%86%E3%81%AA%E3%81%A8%E3%81%93%E3%82%8D
13:32:46 <g000013> とか
13:33:11 <g000013> http://www.aiai.ed.ac.uk/~jeff/lisp/cl-pitfalls
13:33:19 <g000013> とか有用かなと思います
13:33:45 <g000013> 引数の説明で自分がつまったのは
13:33:46 <g000013> &rest引数が必ずしもコピーされない
13:34:37 <g000013> というのと勘違いしたからなのですが、Common Lispの場合は、引数がコピーされないという事項もあったりします
13:35:11 <g000013> では、次回は、12章から再開します
13:35:19 [g000013'out] ; Quit: ERC Version 5.1.2 $Revision: 1.796.2.4 $ (IRC client for Emacs)
20:20:58 [potix2'in]
20:34:03 [potix2'out] ; Remote host closed the connection
20:36:01 [potix2'in]