[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

learning lisp: list



これまでごまかしてきましたが、いよいよ Lisp の真髄にふれる時が来たよう
です。これをマスターすれば「よしま」から「ひさよしま」に移行できるでしょ
う。(やや意味不明)

まずは簡単にリストの説明をします。次に cons の説明を、第2引数がリスト
の場合とそうでない場合に分けて説明します。ここまででプログラムを書く上
で必要になることはわかると思います。その後でリストの正体を説明し、実は
第2引数がリストであろうとなかろうと、cons がやっているのは実は同じこと
なんだということを説明します。これが理解できると、それまでもやもやして
いたリストの仕組みがすっとクリアになると思います。

それではまずはリストからです。簡単に言うと、リストとは0個以上のS式を括
弧でくくったものです。くくられるS式は何でもかまいません。シンボルでも
数値でも文字列でも文字でも OK です。それらを混ぜることもできます。たと
えば、

(a b c)
(1 2 3 4 5)
("A" 1 ?b 'symbol t 3.14)
((a b) (c ) e ((f g) h))

なんかは全部リストです。

最後の例のように、リストのリストとか、リストのリストのリストとか、リス
トのリストのリストのリストのリストのリストのリストのリストのリストのリ
ストのリストのリストとかも作れます。結論: copy & paste は便利だ。

リストの先頭要素を取り出すには car を使います。car は「カー」と読みま
す。

(car '(a b c)) => a

リストから先頭要素をのぞいたものを得るためには cdr を使います。cdr は
「クダー」と読みます。

(cdr '(a b c)) => (b c)
(cdr '(b c)) => (c)
(cdr '(c)) => nil ; () と nil は同じもの

Emacs Lisp は、nil すなわち () に対しては、car も cdr も nil を返しま
す。(nil を返さず、エラーになる Lisp 処理系もあります)

(car nil) => nil
(cdr nil) => nil

car も cdr も、それだけでは元のリストを変更しません。

(setq my-list '(a b c)) => (a b c)
(car my-list) => a
my-list => (a b c)
(cdr my-list) => (b c)
my-list => (a b c)

元のリストを変更したければ setq を使います。

(setq my-list '(a b c)) => (a b c)
(setq my-list (cdr my-list)) => (b c)
my-list => (b c)
(setq my-list (car my-list)) => b
my-list => b

リストの要素一個一個に対してある処理を行う場合の常套句はこうです。

(let ((l '(this is a sample list)))
  (while l
    (my-function (car l))
    (setq l (cdr l))))

まず (my-function (car l)) で l の先頭要素に対して処理を行います。次に
(setq l (cdr l)) するとリスト l は先頭要素を失って長さが1短くなります。
したがって次の (my-function (car l)) ではリストの2番目の要素に対して処
理を行うことになります。以下同様に続き、最後に l が () すなわち nil に
なると while ループが終了するというわけです。

cons に関しては次回。

-- 
TAKAHASHI Naoto
ntakahas@...
http://www.m17n.org/ntakahas/