Against HTML

HTML: when's the last time anybody actually wrote it? I certainly didn't use it for this article, and why should my code be any different? My new lol.fm page needed a template where code and static data could mingle freely, so Scheme naturally came to mind. An s-expression→HTML DSL follows. Maybe it doesn't cover all cases called for in some spec somewhere. I don't care. I was able to whip it up in a few minutes with no external dependencies, which is a win in my book. It takes loose inspiration from Oleg Kiselyov's SXML format, where properties are presented in a list of key value pairs like so: (@ (k v) (k v) ...), but my implementation is from scratch and slightly more verbose in the name of simplicity. Makes use of Chicken's conc builtin, which returns the string representation of all items in a heterogeneously-typed list.

(define ◇ conc)

(define (property key value)
  (if (string? value)
    (◇ " " key "=\"" value "\"")
    (◇ " " key "=" value)))

(define-syntax ▽
  (syntax-rules (! @)
    ((_ ! α (@ ) ω ...) (◇ ">" ω ... "</" (quote α) ">"))
    ((_ ! α (@ (β γ) δ ...) ω ...) (◇ (property (quote β) γ) (▽ ! α (@ δ ...) ω ...)))
    ((_ ! α (@ β δ ...) ω ...) (◇ (quote β) (▽ ! α (@ δ ...) ω ...)))
    ((_ α (@ β ...) ω ...) (◇ "<" (quote α) (▽ ! α (@ β ...) ω ...)))
    ((_ α ω ...) (◇ "<" (quote α) ">" ω ... "</" (quote α) ">")))) 

That's it. Any HTML node can be represented with

(▽ tag (@ (property value) ...) children ...)

like

(▽ html
  (▽ body
    (▽ h1 (▽ a (@ (href "https://zombo.com/")) "Welcome"))))

The can obviously be factored out, but I found it nicer to implement this using recursive macro syntax rather than as a procedure over a plain symbolic list. The syntax-rules cases that begin with ! are internal recursive patterns.

The ideal way, no, but my way. Done.