Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2008-04-19

FORMAT指示子を自作関数で理解する試み

| 21:51 | FORMAT指示子を自作関数で理解する試み - わだばLisperになる を含むブックマーク はてなブックマーク - FORMAT指示子を自作関数で理解する試み - わだばLisperになる

FORMAT関数は便利なのですが、指示子の引数の扱いが全然暗記できないので、せめて良く使う~Aだけでもマスターしたいと思い記憶できるような方法をあれこれ考えてみました。

まず、~Aには、~Aと~@Aがあるのですが、日本語版のCLtL2では「文字列は右に詰められる(もし@修飾子が用いられるのであれば左に)」という記述です。

これだと、~Aは右詰めかと思うのですが、原文は、The string is padded on the right (or on the left if the @ modifier is used) with at least minpad copies of padchar.とのことで、右側がパディング文字で埋められた文字列、つまり、結果としては、日本語でいう左詰めになるというややこしさ。

面倒なので~Aは左詰め、~@Aで逆転、とおぼえることにします。

とりあえず、@の役目は暗記できたので、次に引数です。

説明を読んでも理解できないので、~Aと同じ動作をする関数を作ってみました。

(defun A (s arg &rest params)
  (destructuring-bind
        (&optional (mincol 0) (colinc 1) (minpad 0) (padchar " ")) params
    (let ((pad (max 0 minpad (- mincol (length arg)))))
      (princ arg s)
      (loop :repeat (* pad colinc) :do (princ padchar s)))))

(format t "~@{~10,1,10,'*A~}" "foo" "bar" "baz")
;>>> foo**********bar**********baz**********

(format t (lambda (s &rest args)
            (dolist (x args) ; ~@{ ... ~}
              (A s x 10 1 10 "*")))
        "foo" "bar" "baz")
;>>> foo**********bar**********baz**********

CLtL2の内容をコードに起したつもりではあるのですが、もしかしたら間違ってるかもしれません。

まあ、でも各引数の意味は理解できました。

それで、引数は省略できるのですが、省略にも順序があって、

;; 4つ全部
(format t "~99,88,77,'*A" "foo")

;; 3つの場合
(format t "~99,88,77A" "foo")(format t "~99,88,77,' A" "foo")

;; 2つの場合
(format t "~99,88A" "foo")(format t "~99,88,0,' A" "foo")

;; 1つの場合
(format t "~99A" "foo")(format t "~99,1,0,' A" "foo")

;; 0
(format t "~A" "foo")(format t "~0,1,0,' A" "foo")

という右から順番に省略されたことになります。自作の関数も&restと&optionalの組み合わせで再現してみました。

それで、引数の順番ですが、ここは丸暗記です。

mincol、colinc、minpad、padcharという並びですが、min-col-inc、min-pad-charと結合して無理に憶えたいと思います。ちなみに、~Dでは、また別の並び方をしています…。

まだまだ複雑怪奇な指示子は沢山ありますが、自作してひとつずつ理解していくというのも、まあまあ、アリかなと…。