コンスセルを展開させてみた

そもそも、これを読んで「へぇーへぇーへぇー」とか言ってた。

alist 例.((foo . 1) (bar .2) ...)とplist 例.(foo 1 bar 2 ....)の使うコンスセル数は同じことが知られています。
10分でコーディング x 2 〜リストの破壊的操作篇〜 - わだばLisperになる - cadrグループ

http://cadr.g.hatena.ne.jp/g000001/20090521/1242909362

手動で展開(?)してみると確かに同じだ。へぇーへぇーへぇー。

((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 して修正すれば間違えた定義を残しておける
  • 手動で => 入れるのもういや
  • どーゆー動作するのかの説明にはなってないかも
  • でもどこでどうミスって、どう解決したのかはわかりそう
    • 失敗は記録すべきだと思う、恥ずいけど
  • エントリが長い・・・