ラベル keyword parameters の投稿を表示しています。 すべての投稿を表示
ラベル keyword parameters の投稿を表示しています。 すべての投稿を表示

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ということだから、三章でそぞろ歩きするのはよいとは思う。

Chapter 3 Practical: A Simple Database

前説

この章では、functions, macros and special operators の違いは気にするなと。


CDs and Records

symbolは、まあ名前。
keyword symbolは、symbolのうち、":"から始まるもの。


Filing CDs

特記事項なし。


Looking at the Database Contents

formatって、エラくLoopするな。試す。


CL-USER> (list *db* *db*)
(((:TITLE "Home" :ARTIST "Dixie Chicks" :RATING 9 :RIPPED T)
(:TITLE "Fly" :ARTIST "Dixie Chicks" :RATING 8 :RIPPED T)
(:TITLE "Roses" :ARTIST "kathy Mattea" :RATING 7 :RIPPED T))
((:TITLE "Home" :ARTIST "Dixie Chicks" :RATING 9 :RIPPED T)
(:TITLE "Fly" :ARTIST "Dixie Chicks" :RATING 8 :RIPPED T)
(:TITLE "Roses" :ARTIST "kathy Mattea" :RATING 7 :RIPPED T)))
CL-USER> (format t "~{~a:~10t~a~%~}~%" (list *db* *db*))
((TITLE Home ARTIST Dixie Chicks RATING 9 RIPPED T)
(TITLE Fly ARTIST Dixie Chicks RATING 8 RIPPED T)
(TITLE Roses ARTIST kathy Mattea RATING 7 RIPPED T)): ((TITLE
Home
ARTIST
Dixie Chicks
RATING
9
RIPPED
T)
(TITLE
Fly
ARTIST
Dixie Chicks
RATING
8
RIPPED
T)
(TITLE
Roses
ARTIST
kathy Mattea
RATING
7
RIPPED
T))

NIL
CL-USER>

なる。修正。


CL-USER> (format t "~{~{~{~a:~10t~a~%~}~%~}~}" (list *db* *db*))
TITLE: Home
ARTIST: Dixie Chicks
RATING: 9
RIPPED: T

TITLE: Fly
ARTIST: Dixie Chicks
RATING: 8
RIPPED: T

TITLE: Roses
ARTIST: kathy Mattea
RATING: 7
RIPPED: T

TITLE: Home
ARTIST: Dixie Chicks
RATING: 9
RIPPED: T

TITLE: Fly
ARTIST: Dixie Chicks
RATING: 8
RIPPED: T

TITLE: Roses
ARTIST: kathy Mattea
RATING: 7
RIPPED: T

NIL


なんぞ。

これ、ミニ言語なんですね。


Improving the User Interaction


CL-USER> (defun prompt-read (prompt)
(format *query-io* "~a: " prompt)
(force-output *query-io*)
(read-line *query-io*))
PROMPT-READ


*query-io*って?
REPLで調べると、TWO-WAY-STREAM なんですね。


Saving and Loading the Database

read/print equivalenceを保証するには、with-standard-io-syntaxを使う。

疲れがでてきたので、休憩。