リスト修行(4) SchemeでHTMLを書こう(2)
Schemeのリストを解析してHTMLを構築します。
朝の続きです。イメージタグのリストなんですが、
(img ((src "hoge.gif")))
解析してみると、
<img src="hoge.gif"></img>
空の子要素に対応しきれてません(汗
もうちょっとインテリジェンスにxhtml対応したいところ。
色々変わってきたので仕切り直し。
(require (lib "1.ss" "srfi")) (require (lib "13.ss" "srfi")) ; for Gauche ; (use srfi-1) (use srfi-13) (define ++ string-append) ; (s-tag) -> "html-string" (define (build-html s level) (let* ((tag (symbol->string (car s))) (opt-child (build-option (cdr s))) (opt (car opt-child)) (child (cdr opt-child))) (++ "<" tag opt (if (null? child) " /" (++ ">" (fold (lambda (a b) (++ b (if (not (pair? a)) a (++ "\n" (make-string (* level 2) #\ ) (build-html a (+ 1 level)))))) "" child) "</" tag )) ">"))) ; ((options) child) -> (cons "options" child) (define (build-option s) (cond ((null? s) (list "")) ((and (pair? (car s)) (pair? (caar s))) (cons (fold (lambda (a b) (++ b " " (symbol->string (car a)) "=\"" (cadr a) "\"")) "" (car s)) (cdr s))) (else (cons "" s))))ナドの実現可能性について考察しました ( ; test (define head `(head (title "ボクノス"))) (define footer `(div ((class "footer")) "by Boxnos")) (define s-tag `(html ,head (body (h1 "ボクノス") (div ((class "entry") (id "foo")) (h2 "今日のひとこと") (p "ちょっと大変だった。")) (div ((class "entry") (id "bar")) (h2 "今日のふたことめ") (p "転んでも泣かない。") (img ((src "img/hoge.gif"))) (br)) ,footer))) (build-html s-tag 1)
かなりスッキリ書けた気がします。
実行してみると・・・。
<html> <head> <title>ボクノス</title></head> <body> <h1>ボクノス</h1> <div class="entry" id="foo"> <h2>今日のひとこと</h2> <p>ちょっと大変だった。</p></div> <div class="entry" id="bar"> <h2>今日のふたことめ</h2> <p>転んでも泣かない。</p> <img src="img/hoge.gif" /> <br /></div> <div class="footer">by Boxnos</div></body></html>
インテリジェンスなインデントも付きました(Scheme風)
リストの先頭がタグ、先頭の子要素が2重のリストならオプションという条件を除けば、SICPのmap再帰(fold使ったけど)と同じ形で構築できる事がわかった。
追記
効率化の話。
- Gauche ユーザリファレンス: 11.40 text.tree - 怠惰なテキスト構築
- 単純にstring-appendを繰り返し呼んでしまうと、中間結果の文字列を保持するためだけにメモリアロケーションが多発しますし・・・
- テキストの断片をつなぎ合わせるのを本当に必要になるまで遅らせることです。
「遅らせる」と。
むむ?
("<html>" ("<head>" (....) "</head>") (...) "</html>")
というテキストのツリーリストを作っておいて(実際はもっとバラバラ)、後で結合したほうがいいということか。こっちの方が効率が良さそうだ。
-
- 場合によっては、トラバースしながらテキストを出力すれば事足りてしまうので
おぉぉぉぉぉ。頭いいな。他の言語にも応用が効きそう。
追記2
SXMLというS式で書くXMLがあるらしい。