

What Mustache can learn from Clojure - michaelty
http://chrisvest.name/whats-wrong-with-mustache-templates-and-how-it-can-be-improved.html

======
tomdale
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.

~~~
wycats
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.

------
bascule
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>)

~~~
stevelosh

        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.

~~~
bascule
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.

~~~
true_religion
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.

~~~
bascule
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.

------
stevelosh

        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).

~~~
chrisvest
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.

------
LeafStorm
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!

~~~
spooneybarger
You don't push display logic into business logic, you have an adapter for
domain objects to become display objects.

------
grayrest
> 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.

~~~
chrisvest
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.

------
leeoniya
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>

~~~
xnxn
Hmm, you might want to consider a different name for the project, since there
is already a well-known handlebars.js: <http://www.handlebarsjs.com/>

~~~
leeoniya
to be fair, my project (and actually another project before mine -
<https://github.com/getify/HandlebarJS>) existed before wycats's. i'll prolly
change it if i ever decide it needs publicity.

