[plt-scheme] Embedding scheme in web pages

From: Eli Barzilay (eli at barzilay.org)
Date: Fri Jan 19 14:08:21 EST 2007

On Jan 19, Maarten Koopmans wrote:
> Noel Welsh wrote:
> > I don't advocate it as a good way to build web sites (I fact, I
> > think the opposite) but if you want to embed Scheme
> 
> Why not? Generating html from x-expressions feels design-wise
> sub-optimal.

I'd argue that generating html from any code is super-optimal -- in
the sense that it's both as convenient to write and manage as html,
but it is easier to maintain and extend so it's also good for problems
you didn't yet encounter.

But for the choice of code, I (personal opinion alert) prefer
functions than xexprs -- which doesn't contradict each other since I
can just

  (define p list)
  (define b list)
  ...etc...

and then use these things as functions.  The advantage there is that
there is no confusion over what's quoted and what's code, and since
they're all functions, you can easily extend them.

Here's a quick example:

  > (require (lib "kw.ss"))
  > (define (keyword->symbol k) (string->symbol (keyword->string k)))
  > (define (keys->props ks)
      (if (null? ks)
        '()
        (cons (list (keyword->symbol (car ks)) (cadr ks))
              (keys->props (cddr ks)))))
  > (define-syntax defxexpr
      (syntax-rules ()
        [(defxexpr name)
         (define/kw (name #:all-keys ks #:body body)
           (list* 'name (keys->props ks) body))]))
  > (define-syntax defxexprs
      (syntax-rules ()
        [(defxexprs name ...) (begin (defxexpr name) ...)]))
  > (defxexprs html head title body h1 h2 p b i u)
  > (html (head (title "Foo"))
          (body #:bgcolor "white" (h1 "Foo") (p "Some text")))
  (html () (head () (title () "Foo")) (body ((bgcolor "white")) (h1 ()
  "Foo") (p () "Some text")))

>From this you can easily generate html:

  > (require (lib "xml.ss" "xml"))
  > (xexpr->string
     (html (head (title "Foo"))
           (body #:bgcolor "white" (h1 "Foo") (p "Some text"))))
  "<html><head><title>Foo</title></head><body bgcolor=\"white\"><h1>Foo</h1><p>Some text</p></body></html>"

But you don't want to write the same code over and over -- so you
abstract:

  > (define (mypage title* . body*)
      (html (head (title title*))
            (apply body #:bgcolor "white" (h1 title*) body*)))
  > (xexpr->string (mypage "Foo" (p "Some text")))
  "<html><head><title>Foo</title></head><body bgcolor=\"white\"><h1>Foo</h1><p>Some text</p></body></html>"

[Disclaimer: this is my personal favorite approach; IIUC, WebIt is
very similar, but I never used it seriously.]

The only major problem with this approach for making web content is
that writing text in Scheme strings becomes a major hassle.  This is
where scribble will get in -- it will eventually allow you to use

  @html{@head{@title{Foo}}
        @body[bgcolor="white"]{@h1{Foo}@p{Some text}}}

as a more convenient syntax for using lots of text in Scheme.  (But
this is still work in progress that requires nurturing.)

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!


Posted on the users mailing list.