20 comments

[ 4.1 ms ] story [ 53.9 ms ] thread

    However, there appears to be a set of common denominators
    that can be used to represent all possible 
    data-structures: Maps or dictionaries, lists, strings, 
    numbers, boolean and null.
I'd add sets to this list. You can kind of simulate them using a map where the keys are the members and the values are anything, but they just work more smoothly when you have real support for them (like in Python and Clojure, but not Javascript/JSON).
I was wondering whether to add sets to the list or not. In the end I decided not to because they look just like lists for the purpose of destructuring and I liked how this list of things matched what JSON provides, plus as you say, they can be simulated. It also left me with one less thing to explain, except now that it didn't.
As a user of Clojure and an onlooker of things like mustache (and handlebars) who has used neither of the latter, this post left me incredibly confused. I like the points about destructuring and having something like a let binding. Those seem like useful addition.

However, about half the post discusses how "looping and conditional branching are conflated", and the end focuses on adding a separate branching construct to what's supposed to be a logic-free templating language. So I guess what he's trying to say is he wants to add logic to a logic-free templating language. It seems like he missed the point of Mustache: Looping and branching are conflated by design to eliminate logic from the template.

About the only way I see the connection between Clojure and Mustache at all is through the potential value destructuring could bring, and destructuring isn't exactly a feature which is unique to Clojure (CoffeeScript, Scala, and Erlang come to mind). Otherwise this post is apples and oranges: Clojure macros are about as far as you can get from a logic-free templating language. I'm wondering if the additions he proposes are sufficient to turn what's supposed to be a logic-free templating language into a Turing-complete one (see this example of why XSLT is Turing-complete: http://www.unidex.com/turing/utm.htm)

    Looping and branching are conflated by design to eliminate logic from the template.
That doesn't eliminate logic, it just makes it annoying and obtuse.

You can still branch in mustache templates, and you can still loop. No particular kind of logic has been eliminated. But now you need to know what a particular item happens to be in order to know what the magic branch/loop operator is going to do.

About the only thing it prevents is saying "show this if X is truthy", but only prevents it when X is a list! Removing the ability to do something for some arbitrary objects doesn't make the language clean and logic-free, it makes it annoying and complicated.

Except there's no logic in the language itself, from the perspective of Mustache what you're doing is purely declarative.

Adding an explicit "if" operator does introduce logic into the language, and may very well make the language sufficiently expressive to be Turing complete.

It wouldn't make it turning complete because while the template could read the hypothetical infinite tape, and write infinitely to another tape---it can't write what its written so its prohibited from being turing complete.

It's basically a finite state machine.

Now you can do a whole lot with a FSM---and lo, some people will claim that our current brand of machines are only realistically as powerful as FSMs because of the lack of infinite memory.

The proposed changes, particularly tail recursion, an if operator, and a zip operator in effect give you a functional language with immutable state.

While you can't "write" to the Turing tape as a side effect as the language is immutable, you can create a new "tape" from previous states which is a modified version of the old tape.

I don't understand the idea that mustache is logicless.

Why is something that shows a message "only if person has a truthy value":

  {{#person}}
    Hi {{name}}!
  {{/person}}

different from an `if` (except it becomes a `for` depending on the value of the argument)?

As long as you use values consistently it is never the case that a single person object referred by a variable "person" transforms into a set of people.

I'm sorry the article left you confused. It did end up a bit on the long side and is probably not as well edited as it could have been.

You do not eliminate, or even reduce, the amount of logic at work by conflating looping and branching because now, apart from the normal function of these constructs, the language (or its runtime) is also making decisions about which one of these to use when given a particular piece of data.

The truth is that Mustache isn't logic-free, because it has looping and branching, and it can even call methods and functions with its lambda feature. The only template language I know of that is actually logic-free is Rife Templates: http://rifers.org/wiki/display/RIFE/GuideTemplates.html What you discover when you use that system, is that templates without logic can't really do much, so you have to control them with logic that sits outside of the templates.

As for destructering, I considered adding a Haskell example, but that idea didn't really work with where I was going with the story on data. In the end I am the most familiar with Clojures destructuring, plus its data story was a really good match here, so I just stuck with it.

Handlebars (handlebarsjs.com) solves several of these issues:

Items in lists don't have to be objects with fields; you can display primitives like strings and numbers by using {{this}}:

  {{#each tags}}
    <li><a href="tags.html#{{this}}">{{this}}</a></li>
  {{/each}}
Shadowing properties from parent context objects isn't a problem. Handlebars allows you to reach parent contexts with a '../' notation:

  {{#each comments}}
    <h2><a href="/posts/{{../permalink}}#{{id}}">{{title}}</a></h2>
    <div>{{body}}</div>
  {{/each}}
Regarding looping and conditional branching, Handlebars has an {{#if}} helper that does not evaluate to true for empty arrays:

  {{#if authors}}
    {{#each authors}}
      {{firstName}} {{lastName}}
    {{/each}}
  {{else}}
    No authors to display.
  {{/if}}
I don't fully understand the complaint about recursive data structures. I usually just register a helper that can invoke itself recursively.
It's worth noting that #if, #each etc. are not built-in structures. They are simply helpers that you can register in the host language. Block helpers receive the block as a function that can be invoked as though it was a top-level template.

Consider the simple #with helper:

  Handlebars.registerHelper('with', function(object, options) {
    // invoke the sub-template passed as a block to the with helper with the object parameter
    return options.fn(object);
  });
And its usage:

  {{#with person}}
    Name: {{name}}
  {{/with}}
This means that you can build arbitrary control structures and iterators in the host language and expose them to Handlebars.
> Items in lists must be objects with fields because it is always decomposed, and there is no way to get a handle on the list item itself.

    {{%IMPLICIT-ITERATOR}}
    {{#foo}}
      {{.}}
    {{/foo}}
But...Handlebars.
Yes, Handlebars. I much prefer {{this}} to {{.}}, which at first glance looks a bit like a Perl 6 or Haskell operator rather than a dot surrounded by tags.
I did not know about the {{.}} construct when I wrote that article, but have since been told about it a couple of times. It is indeed a useful thing that would have resolved one of the issues I wrote about. However, it is not in the Mustache spec, nor is it implemented in the particular Mustache implementation, Pystache, that I happen to be using. It could be that Pystache is just behind the curve. I don't know.

I have also since found out about Handlebars.js. It looks nice. If Mustache is the 80% solution then Handlebars.js is probably the 99% solution or something like that. Except I would need an implementation in Python, and I haven't come across one.

To be honest, I have never seen the appeal of logic-less templates to begin with. I can understand wanting a sandboxable template engine independent of language, but that doesn't necessarily translate to "lack of logic."

And yeah, it's easier to shoot yourself in the foot with templates that have logic, but on the other hand with logic-less templates you may need to do something that the template language won't let you do, and then you have to go and write some more code in your domain logic. Which means that you're doing something even worse than pushing your business logic into your display logic - you're pushing your display logic into your business logic!

I think mustache is at its core a reaction to ERB, which allows for pretty baroque logic in templates. Mustache goes all the way in the other direction (which is really not any better).
You don't push display logic into business logic, you have an adapter for domain objects to become display objects.
i've also had a few quibbles about the way Mustache is specced - i felt like it was 80% there, but forced too-verbose templates. i re-implemented and modified it a bit to alleviate some of the ambiguity. never had a chance to do full docs, but the js code/readme is up on github if anyone wants to check it out: https://github.com/leeoniya/handlebar.js