リスト修行(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使ったけど)と同じ形で構築できる事がわかった。

追記

効率化の話。

「遅らせる」と。

むむ?

("<html>" ("<head>" (....) "</head>") (...) "</html>")

というテキストのツリーリストを作っておいて(実際はもっとバラバラ)、後で結合したほうがいいということか。こっちの方が効率が良さそうだ。

    • 場合によっては、トラバースしながらテキストを出力すれば事足りてしまうので

おぉぉぉぉぉ。頭いいな。他の言語にも応用が効きそう。

追記2

SXMLというS式で書くXMLがあるらしい。