2008年1月3日木曜日

Chapter 3 Practical: A Simple Database (Continued)

Querying the Database

evenpの名前空間の指定に#'が必要なのはわかるが、なんでlambdaにも#'がいるんだろ?
試す。

CL-USER> (remove-if-not #'evenp '(1 2 3 4 5 6 7 8 9))
(2 4 6 8)
CL-USER> (remove-if-not #'(lambda (x) (= 0 (mod x 2))) '(1 2 3 4 5 6 7 8 9))
(2 4 6 8)
CL-USER> (remove-if-not (lambda (x) (= 0 (mod x 2))) '(1 2 3 4 5 6 7 8 9))
(2 4 6 8)
CL-USER> (remove-if-not evenp '(1 2 3 4 5 6 7 8 9))
; Evaluation aborted.
CL-USER>

ふむ。lambda は #'なしでもOKなのか。

keyword parameters のところが頭がごちゃごちゃしたのでまとめる。

まず、

(defun foo (&key a b c) (list a b c))

これ。&keyの後ろとbodyの変数が一致しないとどうなる?

CL-USER> (defun (&key a b d) (list a b c))
; Evaluation aborted.

エラーとなると。それからデフォルト値が指定できると。

CL-USER> (defun foo (&key a (b 20) c) (list a b c))
FOO
CL-USER> (foo :a 1)
(1 20 NIL)
CL-USER>

引数として与えられたかどうかをbodyに渡せる。

CL-USER> (defun foo (&key a b (c 30 c-p)) (list a b c c-p))
FOO
CL-USER> (foo :c 1)
(NIL NIL 1 T)
CL-USER> (foo)
(NIL NIL 30 NIL)

なる。

CL-USER> (defun where (&key title artist rating (ripped nil ripped-p))
#'(lambda (cd)
(and
(if title (equal (getf cd :title) title) t)
(if artist (equal (getf cd :artist) artist) t)
(if rating (equal (getf cd :rating) rating) t)
(if ripped-p (equal (getf cd :ripped) ripped) t))))

WHERE

これは何してるんだっけ?

  • selectに渡すselector関数を作るための関数。
  • selector関数は、述語であり、*db*の各レコードに対して、t or nilを返すもの。
  • andの中の構造をみると、このwhere関数は、与えられた全ての条件を満すものをtとする述語。
  • (if hoge (...) t)なんで、条件が与えられてないものはtとする。
  • rippedについては、条件が与えられたときの値がt or nilなので、supplied-pを使用する。

ということか。


Updating Existing Records-- Another Use for WHERE

setf の詳細はChapter 6ということなので、スルー。
mapcar, when, funcallの説明は無し。まあスルーだが、Lisp系の言語をかじったことが無い人はこのあたりで、何がなんだかということで脱落しそうだが。
そういえば、破壊的操作に!をつけるというルールはないんですね。


Removing Duplication and Winning Big

マクロのクラッシュコース 的のもの。

さて、三章までを読んだところでの感想は。

  • CLerの言語の認識がこのような感じだとすると、すでに言語コアとライブラリの区別は認識から消失しているのかもしれない。とすると、CLを使ってCLerがプログラミング初学者に教えるよりも、Schemeで教えた方がよいと思う。少なくとも、R5RSとSRFIとは分離しているので。
  • なにか、昔Rubyを学んだときと同じ感触なような。。。
  • 明示的な再帰が出てこなかった。LOOP多用。
  • Practicalということだから、三章でそぞろ歩きするのはよいとは思う。

0 件のコメント: