mokeheheのScheme日記

ツッコミ、添削大歓迎です。いろいろ教えてください。

2007-12-31

プログラミングGauche」の本が出る

プログラミングGauche - Ohmsha

Gauche 作者の川合史朗さんが監修、内容はno titleに大幅に加筆修正したもの、Kahua という継続ベースのアプリケーションフレームワークを使った内容、とか。超期待だぁ~!

[] Practical Common Lisp第3章

実践:シンプルなデータベース
  • 関数マクロとスペシャルオペレータ:ここでは説明しないけど、ちょっとずつ違うと思ってくれ
  • plist(プロパティリスト)
  • シンボル:名前だと思ってくれ
    • 「:」始まりでキーワードシンボルという、特殊なシンボルになるとは初めて知った
    • Rubyでのシンボルですね
  • (list :a 1 :b 2 :c 3) でplist作成
  • (getf (list :a 1 :b 2 :c 3) :a) でplistから取り出し
  • プロンプトを出してCD情報の入力補佐関数
    • *query-io* がよくわからず。(setf *query-io* t) 、(read-line) 、と変更
    • y-or-n-p はミニバッファにプロンプトが出て、キーを押した後も消えない
    • with-standard-io-syntax が定義されてない。無視。
データベースクエリ
  • (select :artist "Dixie Chicks") で探せるようにしよう
  • remove-if-not : 二重否定で分かりづらいけど、Haskell でいうところの filter
    • remove といっても、元のリストを変更するわけではなく、変更したものが戻り値として返る
(select (where :artist "Dixie Chicks"))
(select (where :rating 10 :ripped nil))

と書けるようにするのは見事としかいいようがない。

レコードの更新
(コードの)重複を削除して、大きく勝利
  • where 関数内で、要素ごとに下のように書いているのが美しくない!
(if title (equal (getf cd :title) title) t)
  • それに :title とか渡してるところで、渡してないものまで実行時にチェックするのがムダ
  • そこでマクロですよ
  • マクロコンパイル時に実行されるから、実行時にはノーコストだよ
  • (loop while fields ...) というのがエラー
    • (loop ...) は xyzzy では無条件ループ
    • (while fields ...) に変更
  • collecting とは?
    • loop~collecting で、結果をリストとして返す?
  • xyzzy lisp で make-comparisons-list はこんな感じかな?
(defun make-comparisons-list (fields)
  (let ((ls ()))
    (while fields
      (push (make-comparison-expr (pop fields) (pop fields)) ls))
    (reverse ls)))
  • macroexpand-1 で、マクロを展開した結果が見れる
(macroexpand-1 '(where :title "Give Us a Break" :ripped t))
#'(lambda (cd) (and (equal (getf cd :title) "Give Us a Break") (equal (getf cd :ripped) t)))

ここまでほとんど一切細かい文法や仕組みを説明しないのもすごいな。ある程度分かってる人前提?

Wrapping Up


補習
  • update中のコードの重複を取り除いてみる
  • (setf (getf row :title) title) のようなリストを作るマクロを作ればいい
  • where のときに習って:
(defun make-setf-expr (field value)
  (list 'setf (list 'getf 'row field) value))

(defun make-setfs-list (fields)
  (let ((ls ()))
    (while fields
      (push (make-setf-expr (pop fields) (pop fields)) ls))
    (reverse ls)))

(defmacro update (selector-fn &rest clauses)
  `(setf *db*
         (mapcar
          #'(lambda (row)
              (when (funcall ,selector-fn row)
                ,@(make-setfs-list clauses))
              row) *db*)))
  • defmacro 内の、selector-fn にカンマをつけるのがわからなくてハマッた
  • こうなると更に、where と update をまとめたくなるのう

りっぷるりっぷる2008/09/08 22:33>xyzzy lisp で make-comparisons-list はこんな感じかな?

こんなのは、いかがでしょうかー。

(defun make-comparisons-list (fields)
(if fields
(cons (make-comparison-expr (first fields) (second fields))
(make-comparisons-list (rest (rest fields))))
nil))

トラックバック - http://sicp.g.hatena.ne.jp/mokehehe/20071231