Common Lisp Tips
Lisper達の情報を共有する場所
関数
関数を定義するときは defun (DEfine FUNction) を使います。
自作した関数を公開する場所(誰かが改良してくれるかも)
- リストのn番目に要素を追加する
(defun add-to-ls (item ls n) (cond ((<= n 1) (cons item ls)) ((null ls) (cons item nil)) (t (cons (car ls) (add-to-ls item (cdr ls) (- n 1))))))
末尾呼び出しver (add-to-ls (item lst n &optional (head '())) (cond ((<= n 1) (nconc (nreverse head) (list item) lst)) ((null lst) (nconc (nreverse head) (list item))) (t (add-to-ls item (cdr lst) (1- n) (cons (car lst) head))))))
いろんな等しさの述語
- eq 「同じオブジェクトか?」アドレスを比較しているらしい。動作は処理系依存。
- eql 「同じオブジェクトか?」eqとの違いは処理系に依存しないところ(シンボルとアトムの違いとする情報もあるけどよくわかりません)。
- = 「同じ数(number)か?」
- equal 2つのリストは等しいか?、調べるときに使ったりする。
- equalp 2つのベクトルは等しいか?、を調べられる1番大雑把な等しさの述語
集合に関する関数
1つのリストを1つの集合として見る。 ls1='(1 2 3 4), ls2='(3 4 5 6)とする。
- 和:(union ls1 ls2)->(1 2 3 4 5 6);;順番は保証されない
- 差:(set-difference ls1 ls2)->(1 2);;順番は保証されない
- 積:(intersection ls1 ls2)->(3 4);;順番は保証されない
- 排他的論理和:(set-exclusive-or ls1 ls2)->(1 2 5 6);;順番は保証されない
- 重複しない場合に追加(非破壊):(adjoin 5 ls1)->(5 1 2 3 4),(adjoin 4 ls1)->(1 2 3 4)
- 重複しない場合に追加(破壊):(pushnew 5 ls1)->(5 1 2 3 4)
- 先頭から何番目?:(position 2 ls1)->1
- 何個あるか?:(count 1 '(1 1 2 1 2 3 1 2 3 4))->4
- 列の部分コピー:(subseq ls1 1 3)->(2 3)
doとdo*
doとdo*はどちらも繰り返しの構文。
どちらも下記の形式
(do ((変数名 初期値 step-form)...) (test 返り値) body)
- 初期値で変数を束縛
- testが真であれば返り値を返し、偽であればbodyを評価、step-formの評価値で新たに変数を束縛
- testが真であれば繰り返しを終了し、偽であれば繰り返す。
doとdo*でstep-formの評価順?が異なる。
例
(do ((temp-one 1 (1+ temp-one)) (temp-two 0 (1+ temp-one))) ((= 3 temp-two) temp-one)) => 3 (do* ((temp-one 1 (1+ temp-one)) (temp-two 0 (1+ temp-one))) ((= 3 temp-two) temp-one)) => 2
- doは全てのtest-formを一斉に評価(前回の変数の値を見る)
- do*は上のtest-formから順に評価(最新の変数の値を見る)
上記の例での変数の値の移り変わり
- do
- temp-one 1->2->3
- temp-two 0->2->3
- do*
- temp-one 1->2
- temp-one 0->3
Keyword(s):
References:[プログラミング]