人生は勉強ブログ

https://github.com/dooooooooinggggg

Common Lispの基礎的な文法4

あくまで自分用のメモ。

今後の実装の時に、簡単に振り返るための記事。

進めている本は、Land Of Lisp

Land of Lisp

Land of Lisp

前回の記事の続き。

blog.ishikawa.tech

今回の記事では、lambdalist周りについてやっていく。

lambda

lambdaを使うと、名前を与えずに関数を作れる。

例えば、渡した数を半分にする関数。

(defun half(x)
    (/ x 2))

;; これを埋め込む。これは、halfという関数を、無名化したもの。
(lambda (n) (/ n 2))

;; これを実行すると、以下のようになる。
(mapcar (lambda (n) (/ n 2)) '(2 4 6))
;; (1 2 3)

これがマクロ

lambdaはlispの中で特に大事らしい。

説明がかなり細かく書いてあったが、今の自分にはその重要性を身を以て実感することができていないため、ここでは省略する。

List

Lispにおいて、Listは、Linked Listのような構造をしている。

前にも書いたかもしれないが、リストは、その一個一個がコンスセルとなっている。

一個のコンスセルには、2つの要素がある。

一個目は、その値自身。二個目は、次の要素へのアドレスのようなもの。

2個目の要素がnilだった場合、その要素はリストの終端を意味している。

また、最後の要素を、nilではなく、リストの先頭に指定することもできる(循環リスト)

しかし、これは要素数が無限になるので、そのままだとREPLが混乱する。

これを避けるために以下の手続きをとる。

;; 通常のList
(cons 1 (cons 2 (cons 3 nil)))
;; (1 2 3)


(defparameter foo (list 1 2 3))

;; 末尾の情報、本来nilになるべきところを、先頭の要素に向ける。
;; これをする際は、以下のコマンドを叩いて、REPLにそういうことをすることを知らせておかないといけない。
(setf *print-circle* t)

(defparameter foo (list 1 2 3))
;; 最後の要素に、fooを代入
(setf (cdddr foo) foo)

;; 要は、(1 2 3)というのは、
(cons 1 (cons 2 (cons 3 nil)))
;; となっていて、そのnilに、fooを代入しているということ

alist

コンスセルから作られるもののデータ構造の中でも、特に便利なのは、連想リスト、別名alistと呼ばれるもの。

例えば以下の例では、それぞれの人のコーヒーの注文を表している。

(defparameter *drink-order* '(
        (bill . double-espresso)
        (lisa . small-drip-coffee)
        (john . medium-latte)))

このalistから、要素を探すには、assocを使う。

(assoc 'lisa *drink-order*)
;; (LISA . SMALL-DRIP-COFFEE)

(push '(lisa . large-mocha-with-whipped-cream) *drink-order*)

(assoc 'lisa *drink-order*)
;; (LISA . LARGE-MOCHA-WITH-WHIPPED-CREAM)

また、assocでは、最初の一つの要素のみを、見つけてくる。(上の例でわかる)

今回は、以上。

次回は、グラフを作る処理の要点をまとめる。