There's a class of templates like CTemplates, Mustache, and lately Handlebars, which are known as "logic-less" templates. My experience lies mostly with Mustache, but in general these templates act on an immutable context representable by simple data protocols like protobufs or json.

The implementations are generally incredibly fast and straightforward, as they limit the user to existence/truthiness checks and looping over object fields and lists. This makes them ideal for client-side templating, which is why a lot of these target JavaScript first, but they've started to find inroads in server-side templating as well, as they keep you honest and they allow you to run the same code on the same contexts on the server or in the browser.

Because true logic is impossible, they prevent you from embedding business logic in the templates. Unfortunately, they also prevent you from embedding presentation logic in your templates. I like these templating languages, but I feel like there's something missing. Today, in order to implement a simple paneling system, I had to write this code:

type M map[string]interface{}
panels := []M{}

for i, p := range Panels {
    side := "left"
    if i%2 != 0 {
        side = "right"
    panels = append(panels, M{
        "side":    side,
        "right":   side == "right",
        "content": p.Render(),

And it felt gross. What this does is take a list of panels and embed their content in a list which encodes their position and a boolean variable which lets me know if it is on the right or not (since you cannot check that "side" == "right").

It struck me that this is analogous to the FizzBuzz problem, and while I have generally liked working with logic-less templates, I feel that there must be some middle ground where this kind of pretty prevalent problem should still be easily solvable without resorting to passing closures or determining display logic in the view:

Given a list of panels, place them in divs with an alternating class. Every two panels, place a clearing div. Do the same, but with 3 classes and 3 divs per row.

Oct 15 2012