Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify what the empty string should be treated as. #28

Closed
thegrandpoobah opened this issue Dec 8, 2011 · 9 comments
Closed

Clarify what the empty string should be treated as. #28

thegrandpoobah opened this issue Dec 8, 2011 · 9 comments

Comments

@thegrandpoobah
Copy link

As part of what constitutes truthiness, the spec uses the !! operator as an example for determining truthiness (in the section.yaml file). The problem is that in JavaScript (and possibly other languages, have not tried), the empty string would be coerced into a false value using that logic. Arguably this is not the intented behaviour, but this is never explicitly stated and currently open to interpretation and implementation differences. Although implementation differences are okay in some circumstances, I think this one should be eliminated by explicitly stating the role that the empty string plays.

For reference, consider the following issues logged under Mustache.js (although not spec-compliant, it is close enough in regards to truthiness to validate this issue):

@pvande
Copy link
Contributor

pvande commented Dec 8, 2011

The expectation is that the empty string is treated like any other value: if the host language treats it as falsey, it's falsey, otherwise it's truthy. The behavior of coercing the empty string to false in JavaScript is as described and as expected.

@pvande pvande closed this as completed Dec 8, 2011
@groue
Copy link

groue commented Dec 9, 2011

The ruby implementation treats empty strings as falsey values, though they're not in the ruby language...

Plus inconsistent behaviors across implementations would jeopardize the host-language-agnosticity of the templates, wouldn't they? (think about templates that can be used both server- and client-side: it would be a pity that a single empty string would ruin hours of careful template-crafting)

Finally, {{#title}}<h1>{{title}}</h1>{{/title}} is a handy way to output a tag if and only if it would have some content.

@pvande
Copy link
Contributor

pvande commented Dec 13, 2011

@groue My copy of the Ruby implementation does the right thing.

$ irb -rubygems
require 'mustache'
>> require 'mustache'
=> true
>> Mustache.render('This is a {{#test}}truthy{{/test}} string!', { :test => '' })
=> "This is a truthy string!"

The reusability of the templates suffers in direct proportion to the number of host-language-specific features you leverage. If you're writing {{#title.empty?}} a bunch, you're going to run into similar problems.

Furthermore, if a decision were made by us to differ arbitrarily from our host languages in terms of what truth means, we only end up alienating ourselves from most of our potential users.

@mahonnaise
Copy link

There are many languages which don't have a concept of "truthy" and "falsy".

E.g. in Java there is only one thing which is true. It's a boolean with the value of true.

An array isn't true, a string isn't true, an empty string isn't true, an object isn't true, 5 isn't true, new Boolean(true) isn't true, Boolean.TRUE isn't true, ...

I fully agree with groue. Host-language agnostic templates are a very important selling point of Mustache. To be honest, it's the only reason why I care about Mustache.

@pvande
Copy link
Contributor

pvande commented Dec 19, 2011

@mahonnaise There's a strong distinction to be made between host-language-agnostic and host-logic-agnostic templating.

Javascript, Python, PHP, and Perl will all insist that empty strings are logically false. Ruby will insist that empty strings are logically true. Java will insist that empty strings have no logical value.

Python, PHP, and Perl all insist that empty arrays or lists are logically false. Ruby and Javascript insist that empty arrays or lists are logically true. Java insists that empty arrays or lists are not booleans.

Perl and PHP also insist that the number 0 and the string "0" are logically false. Javascript and Python concede the number 0, but treats the string "0" as truthy. Ruby considers them both truthy, and Java holds its ground.

Host-language-agnostic templating is very much an important part of Mustache, but so are the host language's semantics. If Mustache behaves according to its own set of logical rules, then the user is forced to remember not only the logical constructs of the host language, but where Mustache's logical beliefs differ.

If these are rules are complex enough ("0, "0", and any string starting with /nan/i are false..."), then the user needs to resort to looking at the documentation every time they fail unexpectedly. If they're reasonably simple ("'Empty' is falsey, everything else is truthy...") the task is simpler, yet it still requires a paradigm shift for some users. The friendliest thing we can do for every user (novice and expert alike) is to guarantee the same semantics as the host language.

In the end, it's not only possible but simple to write host-language-agnostic templates with Mustache. Boolean (and Inverted) sections should be passed boolean arguments. Iterative sections should be passed list-like arguments. No more, no less. (As a convenience, if your language allows non-boolean types to be used as booleans, Mustache will do that coercion for you.)

If your template expresses the semantic intent (e.g. {{#has_title}} vs. {{#title}}), it doesn't matter what host language you're using: the View should return a value appropriate for the language. Semantic templates are perfectly agnostic; when you start to push the interpretation into the template itself, you widen the gap between implementations.

tl;dr: Mustache templates are host-language-agnostic, but reliance on host language features (like boolean coercion) in your templates means more difficulty in the porting process. The host language features are provided as a convenience, not a crutch.

@groue
Copy link

groue commented Dec 19, 2011

@pvande "My copy of the Ruby implementation does the right thing."

Huh? I'm pretty sure Ruby mustache not always had.

Anyway, empty string has a pretty bad status in the Ruby implementation:

Mustache.render("{{#empty_string}}Truthy.{{/empty_string}} {{^empty_string}}And falsey, too{{/empty_string}}", {:empty_string => ''})
=> "Truthy. And falsey, too"

@groue
Copy link

groue commented Dec 19, 2011

In the end, it's not only possible but simple to write host-language-agnostic templates with Mustache.

This is utterly wrong when you develop your template on an single platform, because you'll rely on implementation side effects.

And then you get bitten.

@mahonnaise
Copy link

Ruby and Javascript insist that empty arrays or lists are logically true.

See the "Inverted Sections" example over at http://mustache.github.com/mustache.5.html

If you say that it's fine that empty arrays are treated as logically true, then this kind of thing will be impossible without modifying the data and template:

{{#repo}}
  <b>{{name}}</b>
{{/repo}}
{{^repo}}
  No repos :(
{{/repo}}

Also, the people who take care of the back-end aren't necessarily the same people who take care of the front-end. In some cases they don't even work at the same company.

This stuff should be the same everywhere. You shouldn't need to know in which language the Mustache implementation is written. You shouldn't need to know what's considered truthy/falsy in that language. You shouldn't have to modify your templates if a different Mustache implementation is used. You should be able to use the same templates on both sides without being forced to use JavaScript on the server-side.

Isn't that what Mustache is all about? Isn't that Mustache's unique selling point?

@niko
Copy link

niko commented May 24, 2012

I second @groue here: Empty string handling is broken. Either it should be falsey or truthy. This must be fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants