Higher Order Blog


There is still HOPE for templates...

06 Apr 2008

I am interested in JavaScript. One reason I got interested in JavaScript was a discussion about templating languages with Trifork colleagues Joakim and Kresten (or perhaps it would be more correct to say that we were discussing better ways of implementing the View-part of traditional Model-View-Controller web applications). I ended up liking the idea that the best approach was to dump templates altogether and write the whole client application in a high-level language, i.e., JavaScript, rather than using any of the existing templating languages. Hence, the interest in JavaScript. In fact, I got so interested in JavaScript that I forgot all about templating languages again. That was until recently when I remembered the original discussion, and started thinking about templating again. It was actually some good fun thinking about this -- who would have thought? Anyway, enough about me... Here is the idea.

The language is called HOPE Templates, or just HOPE. The acronym is for Higher-Order Partially Evaluated Templates. Obviously two important ideas are (i) higher-order: templates are a type of functions and the input and output of these functions can be templates; (ii) templates are partially evaluated, meaning that general templates with multiple inputs can be specialized with respect to each input.

That's it! These two powerful concepts are the core of the language. I'll illustrate the HOPE idea through a series of examples.

Simple Template 1:

Hello World!

Any string is a (zero-order) template; when applied, the above template always outputs 'Hello World!'

Simple Template 2:

HelloTpl = λx.Hello x!
RuleTpl = λx.x, you rule!

This defines two named templates, e.g., 'HelloTpl' takes an input 'x' and outputs "Hello x!", where 'x' is replaced with what-ever the template is applied to. Note the use of λ for template abstraction -- this is to suggest the higher-order functional nature of templates (and it is concise too).

An important concept here is that any text in the program that is not a bound variable (or any language syntax) is just zero-order templates. Conversely, if a variable is bound by a lambda, then its occurrence means to 'insert the input template here'. We allow the α-conversion from the lambda calculus so that λx. Hello x! is the same as λy. Hello y!. This means that we can insert/apply templates without having to escape characters: if there is a clash we can always just α-convert.

So far nothing new.

Simple Template 3:

ConcatTpl = λx,y,arg. (x arg)(y arg)

This template is meant to be used as a higher-order template that takes two templates (x,y) and an argument (arg). It applies each template to the argument.

Example 1:

ConcatTpl HelloTpl RuleTpl ~
  λarg.(HelloTpl arg)(RuleTpl arg) ~
     λarg.(Hello arg!)(arg you rule!)

The application of a template is left-associative so the first line is (ConcatTpl applied to HelloTpl) applied to RuleTpl. The ~ is an equivalence relation invented for this blog posting. You can think of it as meaning 'is the same template as'. I haven't defined it formally, but it must be similar to the lambda calculus conversion rules.

I'm not sure about brackets yet. They are needed for grouping and are definitely not part of the output.

Partial evaluation. Consider the following template:

Tag = λname,clz,content.
<name class="clz">

This is just a normal curried function so we have

Tag div ~
<div class="clz">

However, we can do also partial evaluation (application with respect to one or more named arguments). For example

Tag clz:selected ~
<name class="selected">

Now I think it starts to get interesting ;-)

A final concept I would like is something like the following called operator definition. A simple definition could be:

Mine = λx.I own x!

An operator definition generalizes a simple definition by having variables on both sides of the equality symbol. For example:

x.y = λx,y,z.<x class="y">z</x>

This does several things. First it defines a named template '.', like

. = λx,y,z.<x class="y">z</x>

But it does more! It also allows for the following syntactic sugar: .highlight meaning

.highlight ~λx,z.<x class="highlight">z</x>

and e.g.

div.highlight ~ λz.<div class="highlight">z</div>


div.highlight HOPE! ~ <div class="highlight">HOPE!</div>

Combined with a notion of default values, this looks similar to something we seen before and like ;-), but I believe that it is much more powerful!

Here are a few notes to myself: