連想配列(alist) - Lisp
Lispには連想リストというものがある
連想リスト(association list)、また、alistと呼ばれる。carがキー、cdrが値となる。
carがキー、cdrが値って考え方スッキリしてて好き
> (defparameter *alist* '((hoge (1 2 3)) (fuga (4 5 6)) (piyo (7 8 9)))) *ALIST* > *alist* ((HOGE (1 2 3)) (FUGA (6 7 8)) (PIYO (9 1 2)))
要素の追加にはconsを使う
> *alist* ((HOGE (1 2 3)) (FUGA (4 5 6)) (PIYO (7 8 9))) > (cons (cons 'hogera '(10 11 12)) *alist*) ((HOGERA 10 11 12) (HOGE (1 2 3)) (FUGA (4 5 6)) (PIYO (7 8 9)))
先頭に追加のときはpush
を使うのが楽かも
> *alist* ((HOGE (1 2 3)) (FUGA (4 5 6)) (PIYO (7 8 9))) > (push '(foo (a b c)) *alist*) ((FOO (A B C)) (HOGE (1 2 3)) (FUGA (4 5 6)) (PIYO (7 8 9)))
キーを指定して値を取得
assoc
関数を使うことで指定したキーに一致するリストが取得できる
> (assoc 'hoge *alist*) (HOGE (1 2 3))
値のみ取得したい場合
> (cadr (assoc 'hoge *alist*)) (1 2 3)
assocとpushで値を更新したように見せかける
assocは見つかった最初の要素を返すため、pushすると(最初の要素に追加)、値を更新したことと同じになる。最初、何言ってるのかわかんなくて全然理解できなかった。
> (defparameter *fruits* '((apple (100 red)) (banana (150 yellow)) (peach (300 pink)))) *FRUITS* > *fruits* ((APPLE (100 RED)) (BANANA (150 YELLOW)) (PEACH (300 PINK))) > (assoc 'peach *fruits*) (PEACH (300 PINK)) ;;; 最初の要素に追加 > (push '(peach (500 pink)) *fruits*) ((PEACH (500 PINK)) (APPLE (100 RED)) (BANANA (150 YELLOW)) (PEACH (300 PINK))) ;;; あたかも更新されてるみたいになる! > (assoc 'peach *fruits*) (PEACH (500 PINK))
更新されてるみたいになる。理解できた気がする!!
Land of Lispの説明文を引用
assocコマンドは常に、見つかった最初のエントリを返す。したがってpushコマンドを使うと、assocにとってはそのオブジェクトに対する場所が更新されたのと同じ効果を持つわけだ。pushとassocを使って、以前の値を残したまま、alistの値が変更されたかのように見せることができる。
参考文献
- 作者: M.D. ConradBarski,Conrad Barski,川合史朗
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/02/23
- メディア: 大型本
- 購入: 1人 クリック: 18回
- この商品を含むブログ (19件) を見る
四則演算 - Lisp
コンスセルとconsとcarとcdr
Lispはすべてリストでできている。また、リストとリストを繋ぐ役目にコンスセルというものがある。これはすごい面白い考え方だと思った
コンスセルは2つの部屋(セル)でできている。1つ目のセル(CARと呼ばれる)にはデータなどを指し、2つ目のセル(CDRと呼ばれる)には別のコンスセルやnil
というリストの終わりを示す特別なシンボルを指すことができる。
また、データそのものが入るわけではなく、データの参照を指し示すようになっている。ポインタみたいな?
Lispではコンスセルの連なりとリストは全く同じものとして扱われる。
コンスセルについてはAbout Cons Cellsがわかりやすかった
Lispのプログラムからコンスセルを扱うにはcons
関数を使う。ほかにもcar
とcdr
がある。
cons関数
> (cons 1 2) (1 . 2)
これは、1と2をコンスセルで繋いでいますよっていうこと。リストと区別するために、.
が入っている
> (cons 1 'nil) (1)
第2引数にリストの終りを示す'nil
を渡すと、通常のリストのような表示になる。(1 . 'nil)
と同じ意味。Lispはできるだけ、コンスセルではなくリストとして見せてくれている!
> (cons 1 ()) (1)
Common Lispでは、空のリスト()
とシンボル'nil
は同じ意味となっている。そのためこのようにも書ける。
「空のリストに1を追加したら、1だけのリストになる」と考えればしっくりきた。
どんなリストもコンスセルで表せる!
> '(1 2 3) (1 2 3) > (cons 1 (cons 2 (cons 3 'nil))) (1 2 3) > (cons 1 (cons 2 (cons 3 ()))) (1 2 3)
car関数とcdr関数
コンスセルを扱うための関数であるcar(カー)とcdr(クダー)。それぞれ、コンスセルの部屋の構造と一致している。
car
で1つ目のコンスセルのCARセル。cdr
で1つ目のコンスセルに紐づくデータが取得できる。
> (car '(dog cat chicken)) DOG > (cdr '(dog cat chicken)) (CAT CHICKEN) > (cdr (cons 'b 'nil)) NIL
組み合わせることで取得したい場所を取得できる。ちょっと複雑になるけど。。。
例)2番目の要素を取得する
> (car (cdr '(dog cat chicken))) CAT
cdr
で2番目以降の要素を取得し、それに対してcar
で1番目の要素(2番目)を取得する
一度に取得できる関数も用意されている
> (cadr '(dog cat chicken)) CAT > (cadr '(dog cat chicken)) CAT > (cddr '(dog cat chicken)) (CHICKEN) > (caddr '(dog cat chicken)) CHICKEN > (cdddr '(dog cat chicken)) NIL
各順番のとおりにa
かd
を書けばいいのかも。(car (cdr '(...)))
だから、(cadr '(...))
みたいに。
最後のコンスセルにはnilが入っていることを忘れずに!!!
cdadadr
をやろうとしたら、そんなの無いよ!!!っていわれた。最大4つまでらしい。
> (cdadadr '((peas carrots tomatoes) (pork beef chicken))) *** - EVAL: undefined function CDADADR
list関数
list関数を使うと簡単にリストが作れる。
以下の3つは同じ意味!!
> (list 'dog 'cat 'chicken) (DOG CAT CHICKEN) > '(dog cat chicken) (DOG CAT CHICKEN) > (cons 'dog (cons 'cat (cons 'chicken ()))) (DOG CAT CHICKEN)
nilを含まないデータでcdrを使うと
なんかおもしろいと思った。
> (cons 'a (cons 'b 'c)) (A B . C) > (cdr (cons 'a (cons 'b 'c))) (B . C) > (cddr (cons 'a (cons 'b 'c))) C
.
は要素なのかな!?って思ってみたけど、そんなことはなかった。。。
listとクオートの快適さを実感した
複雑なリストを作るときにちょっと手こずった。
> (cons (cons 'peas (cons 'carrots (cons 'tomatoes ()))) (cons 'pork (cons 'beef (cons 'chicken ())))) ((PEAS CARROTS TOMATOES) PORK BEEF CHICKEN)
((PEAS CARROTS TOMATOES) (PORK BEEF CHICKEN))
ってなってほしい!!
> (cons (cons 'peas (cons 'carrots (cons 'tomatoes ()))) (cons (cons 'pork (cons 'beef (cons 'chicken ()))) ())) ((PEAS CARROTS TOMATOES) (PORK BEEF CHICKEN))
できたけど、ややこしいよ!!!!!!
これをやったあとにlist
やクオートを使うとなんと楽なことか
> (list (list 'peas 'carrots 'tomatoes) (list 'pork 'beef 'chicken)) ((PEAS CARROTS TOMATOES) (PORK BEEF CHICKEN)) > '((peas carrots tomatoes) (pork beef chicken)) ((PEAS CARROTS TOMATOES) (PORK BEEF CHICKEN))
あぁ、楽すぎる...まじでやばい
Lispを始める
Lispになぜか興味を持ってしまい、本まで買ってしまった。
Lispの魅力は
たぶん、もっとあった気がする
Lispの種類
ANSI Common LispとSchemeというのが有名らしい。最近見たのはClojureっていう言語も有名かも?
clispをインストールする
clispというCommon Lispで書かれたコンパイラを使って、書いていく
CLISP - an ANSI Common Lisp Implementation
brew install clisp
clisp --version
さぁ!Lispをはじめるぞ!!
roswellっていうのもあるらしいけど、とりあえず、最初はclispでやってみる。基礎がわかってきたらroswellでやってみよう。
インストール完了時に出てきた文字がちょっと気になった
==> clisp Emacs Lisp files have been installed to: /usr/local/share/emacs/site-lisp/clisp
Emacs!?なんですと!?emacs
とコマンドを打ってみたら、Emacsが起動した。終了の仕方わからなくておどおどしてた。C-x C-c
で終了できた