2016年9月29日

実践common lisp第20章

関数でもマクロでも実現できないものが特殊オペレータ
でいいのかな
QUOTEは確かに関数でもマクロでも実現できそうにない気がする
せっかくなのでQUOTEについて再度触れておくと、なんでこれが必要なのかっていうことなんですけど、Common Lispのソースコードがリストで表現されていて、そのリストの一つ目は関数名(又はマクロ、特殊オペレータ)、二つ目以降が引数っていうルールがあるから例えば
(+ 1 2 3)
はリストの一つ目の+が関数名、二つ目以降の1 2 3が引数になる
そんで例えば(あんまり有用な例が思いつかない)length関数に静的にリストを渡すとして
(length (1 2 3));間違い
と、してしまうとlength関数に渡している(1 2 3)のリストの一つ目の1が関数名として扱われてしまうから実行時にエラーになってしまう
そこでlengthに渡しているリストは一つ目が値で関数名じゃないですよって言う意味で
(length '(1 2 3))
と記述することができるようにQUOTEが存在している
QUOTEは
(quote (1 2 3))
'(1 2 3)
と等価

IFも関数だと実現できないので
あとこのPROGNって言うのが他の言語にはない珍しいもので、これは単純に言うと複数実行するものを一つにまとめるっていうかただそんだけ
インクリメントして出力するとか複数実行する場合PROGNで囲む
(let ((i 0))
(progn
(incf i)
(format t "~A~%" i)))
例えばifの第二、第三引数は一つのS式しか受け付けられないから
(if pred
(progn
(incf i)
(format t "~A~%" i))
(format t "~A~%" i))
と、PROGNで囲む
ただしwhenやunlessは暗黙でPROGNで囲まれるのでいちいち囲む必要がない
最初はめちゃくちゃややこしかったけどなれるとだんだんと分かるようになります

let、labelsも頻繁に使う
Common Lispは同じ変数名、関数名でもお構いなしに利用できるからめちゃくちゃ便利ですよね
C#だと同じ変数名使えないから匿名関数の引数でいちいち変数名を変えないといけないので

その他の特殊オペレータは正直あんまり使うことないんじゃないかなと思う
フロー制御なんて多分普通使っちゃダメなんじゃないのか
いわゆるgoto的な扱いを受けそう
そういえば昔、C#で制御構造として例外使ってる人いたんだよね
びっくりしたね、プログラムの途中でどうしても呼び出し元に制御を戻したいってことで無理やりthrowしてる人いたな、酷かったな
フロー制御はなんて言うか層が違う部分を構築する際に必要になるんじゃないかな
フレームワーク的な層とアプリケーション層と分けて作る場合に必要というかそんな気がする
多値もあんまり使わないかな