妄想format

format の痒いのに手が届かないところ - kozima の日記 - cadr group
「format の痒いのに手が届かないところ」に挑戦! - 'T - cadr group

elisp風のformatもあればエスケープ地獄は逃れられるかなあという事でsrfi-28を写経&改変して使うという色々と間違ってる気がする方法。

(defun format% (format-string &rest args)
  (with-output-to-string (buf)
    (labels
	((rec (format-list objs)
	   (cond ((null format-list) t)
		 ((char= (car format-list) #\%)
		  (if (null (cdr format-list))
		      (error 'format% "Incomplete escape sequence")
		      (case (cadr format-list)
			((#\a #\d)
			 (if (null objs)
			     #1=(error 'format% "No value for escape sequence")
			     (progn (princ (car objs) buf)
				    #2=(rec (cddr format-list) (cdr objs)))))
			(#\s (if (null objs)
				 #1#
				 (progn (prin1 (car objs) buf) #2#)))
			(#\~ (princ #\newline buf)
			     #3=(rec (cddr format-list) objs))
			(#\% (princ #\% buf) #3#)
			(t (error 'format% "Unrecognized escape sequence")))))
		 (t (princ (car format-list) buf)
		    (rec (cdr format-list) objs)))))
      (rec (coerce format-string 'list) args))))

(format t "<ul>~%~{~}</ul>"
        (format% "~%dT<li>~A</li>~%%" 2)
        '(aaa bbb ccc))

;<ul>
;  <li>AAA</li>
;  <li>BBB</li>
;  <li>CCC</li>
;</ul>
;NIL

まともな良い方法は思いつきませんでした。


補助記憶とかあれば短く書けそうなんだけど酷いことになりそう。
以下拡張format妄想

(format "~K~@{~0YT<ul>~%~{~1YT<li>~A</li>~%~}~0YT</ul>~%~}"
        '(2 4)
        '(aaa bbb ccc)
        '(ddd eee fff))

~Kで任意の位置に上書きできるよう修飾子を考えて、あとはレジスタの値を引数で受け取った関数に渡して結果を使うorレジスタに書き込むといった指定子を用意すれば立派なesoteric-languageの完成ですね。

作るのは面白そうだけど書くのはどうだろうな…


ところで

(format t "~{~}" "~4T~A~%" '(a s d f))

この書き方の引数の消費のされ方がよく分からなかったりとかg000001さんのformat-stringの所に関数を渡すという方法を全く知らなかった。
この辺かな。読んでみよう。