コンスセルを展開させてみた
そもそも、これを読んで「へぇーへぇーへぇー」とか言ってた。
alist 例.((foo . 1) (bar .2) ...)とplist 例.(foo 1 bar 2 ....)の使うコンスセル数は同じことが知られています。
http://cadr.g.hatena.ne.jp/g000001/20090521/1242909362
10分でコーディング x 2 〜リストの破壊的操作篇〜 - わだばLisperになる - cadrグループ手動で展開(?)してみると確かに同じだ。へぇーへぇーへぇー。
((foo . 1) . ((bar . 2) . nil)) ;4こ (foo . (1 . (bar . (2 . nil)))) ;4こリストの破壊的操作 - 日々ごちゃごちゃと考える
テスト用の何かを使ってみたくて、コンスセルを展開する関数なんぞ書いてみた。
*scratch* に全部残しといてコメントつけて説明の代わりにする試み
思い出して全部書くのめんどいんで
;;; ヨーイ・・・ドン!! (format-date-string *w3c-dtf*) => "2009-06-03 03:54:53" ;;; spec を定義 (about repr-conscell ;; (repr-conscell '(a b c) は "(a . (b . (c . nil)))" を返す (expect (repr-conscell '(a b c)) (it-returns "(a . (b . (c . nil)))")) ;; (repr-conscells '(a (b c)) は "(a . ((b . (c . nil)) . nil))" を返す (expect (repr-conscell '(a (b c))) (it-returns "(a . ((b . (c . nil)) . nil))"))) => #S(spec ...) ;長いので省略 ;;; 最初に書いたやつ (defun repr-conscell (list) (cond ((null list) "nil") ((atom list) (format nil "~S" list)) ((consp (format nil "(~S . ~S)" (repr-conscell (car list)) (repr-conscell (cdr list))))) (t (error "what?")))) => repr-conscell (verify-spec (find 'repr-conscell *spec-list* :key #'spec-name)) => nil #| 別の buffer に出力されるのでコピペ about repr-conscell: when do (repr-conscell '(a b c)) [Failure #1] - Expected: return "(a . (b . (c . nil)))" * Actually: signaled simple-error: # what? when do (repr-conscell '(a (b c))) [Failure #1] - Expected: return "(a . ((b . (c . nil)) . nil))" * Actually: signaled simple-error: # what? |# ;;; (?_?) ;;; 不安になったのでいろいろ確認 (repr-conscell nil) => "nil" (repr-conscell 'a) => "a" (repr-conscell '(a b)) => error: what? ;;なんで? (defun repr-conscell (list) (format t "list: ~S~%" list) ;呼び出しごとに引数を確認 (cond ((null list) "nil") ((atom list) (format nil "~S" list)) ((consp (format nil "(~S . ~S)" (repr-conscell (car list)) (repr-conscell (cdr list))))) (t (error "what?")))) => repr-conscell (repr-conscell '(a b)) list: (a b) list: a list: (b) list: b list: nil => error: what? (null nil) => t ;;; ごめん、意味がわからない (defun repr-conscell (list) (cond ((null list) "nil") ((atom list) (format nil "~S" list)) ((consp (format nil "(~S . ~S)" (repr-conscell (car list)) (repr-conscell (cdr list))))) (t (error "what?: ~S" list)))) ;エラーったときの list を確認 => repr-conscell (repr-conscell '(a b)) => what?: (b) ;;; (b)?? それは (consp list) を満たすはずなんだが (consp '(b)) => t ;だよなぁ ;;; cond の条件で (consp に list を渡してなかった しかも閉じてなかった (defun repr-conscell (list) (cond ((null list) "nil") ((atom list) (format nil "~S" list)) ((consp list) (format nil "(~S . ~S)" (repr-conscell (car list)) (repr-conscell (cdr list)))) (t (error "what?")))) => repr-conscell (verify-spec (find 'repr-conscell *spec-list* :key #'spec-name)) => nil #| about repr-conscell: when do (repr-conscell '(a b c)) [Failure #1] - Expected: return "(a . (b . (c . nil)))" * Actually: returned "(\"a\" . \"(\\\"b\\\" . \\\"(\\\\\\\" ";ry when do (repr-conscell '(a (b c))) [Failure #1] - Expected: return "(a . ((b . (c . nil)) . nil))" * Actually: returned "(\"a\" . \"(\\\"(\\\\\\\"b\\\\\\\" . ";ry |# ;;; なんてこった、~S じゃなくて ~A に (defun repr-conscell (list) (cond ((null list) "nil") ((atom list) (format nil "~S" list)) ((consp list) (format nil "(~A . ~A)" (repr-conscell (car list)) (repr-conscell (cdr list)))) (t (error "what?")))) => repr-conscell (verify-spec (find 'repr-conscell *spec-list* :key #'spec-name)) => nil #| about repr-conscell: when do (repr-conscell '(a b c)) [OK] returned "(a . (b . (c . nil)))" as expected. when do (repr-conscell '(a (b c))) [OK] returned "(a . ((b . (c . nil)) . nil))" as expected. |# ;;; よろし :) (format-date-string *w3c-dtf*) => "2009-06-03 04:02:23" ;;; ぐむ・・・ ;;; おまけ (defun format-conscell (out cell) (format out "~A" (repr-conscell cell))) => format-conscell (format-conscell t '((foo . 1) (foo . 2))) ((foo . 1) . ((foo . 2) . nil)) => nil (format-conscell t '(foo 1 bar 2)) (foo . (1 . (bar . (2 . nil)))) => nil
感想:xl-behave
- あんま debug には役に立たないかも
- BDD 的にはどーゆー動作するのかイメージ掴めりゃおk
- QA(?)的なテストさせようとするとごちゃごちゃしそう
- 結果は別の buffer に表示させてるんだけど、scratcch でぐちゃぐちゃやるときはその場に出力されてほしい
- 戻り値が nil 固定ってのはいかがなものか
感想:その他
- defun を eval-last-sexp したときに、その defun form を *kill-ring* に追加すると便利かも
- C-y して修正すれば間違えた定義を残しておける
- 手動で => 入れるのもういや
- どーゆー動作するのかの説明にはなってないかも
- でもどこでどうミスって、どう解決したのかはわかりそう
- 失敗は記録すべきだと思う、恥ずいけど
- エントリが長い・・・