Template strings and templates
let tmpl = html
<table> $for address in addresses ${ html
<tr>${"first"}</tr><tr>${"last"}</tr>} </table>
;
let tmpl = addresses => html<table> ${addresses.forEach(address=> html
<tr>${address.first}</tr><tr>${address.last}</tr>).join('\n') } </table>
would be my guess? Similarly for the localization example in the blog post: arrow functions should make it relatively painless to make the template parameters explicit.
Of course, building HTML from nested templates is not the same as filling a flat HTML template with user input, so I'm not sure what the implicit encoding of template parameters will do to this approach.
Does this make sense? Claus
On Fri, Aug 3, 2012 at 1:25 AM, Claus Reinke <claus.reinke at talk21.com> wrote:
let tmpl = html
<table> $for address in addresses ${ html
<tr>${"first"}</tr><tr>${"last"}</tr>} </table>
;let tmpl = addresses => html
<table> ${addresses.forEach(address=> html
<tr>${address.first}</tr><tr>${address.last}</tr>).join('\n') } </table>
would be my guess? Similarly for the localization example in the blog post: arrow functions should make it relatively painless to make the template parameters explicit.
Of course, building HTML from nested templates is not the same as filling a flat HTML template with user input, so I'm not sure what the implicit encoding of template parameters will do to this approach. Does this make sense?
Yes. But you need to say ".map(" rather than ".forEach(" above. See harmony:quasis#nesting.
Thanks for pointing out how much fat arrows help for this use case. I knew it would help but hadn't expected it to help that much. Nice!
On Aug 2, 2012, at 12:02 PM, Axel Rauschmayer wrote:
I love the new name “template strings” for “quasi literals”. Only “tag” seem inferior to “quasi handler”, because that former term is already used in HTML.
I didn't intentionally rename "quasi handler" to "tag". I titled the section of the specification that defines the syntax for specifying a handler as "Tagged Quasis" (after the meeting retitled to "Tagged Templates"). And used the terms "tagged quasi" and "untagged quasi" in the slide deck I presented at the meeting.
I believe I picked up the term "tag" from the BNF used on the Wiki proposal page harmony:quasis#literal_portion_syntax . It says (approximately): QuasiLiteral :: QuasiTag ` LiteralPortion QuasiLiteralTail
The term "handler" is also used in the proposal, but it doesn't appear that either "handler" or "tag" was designated as the "official" terminology.
I think it is fine to refer to a function that are called when evaluating a template string as "template string handler". That will probably often get abbreviated to just "handler".
However, in talking about the syntactic forms it seems awkward to say "a template string with a handler" or a "handled template string". In those situations it may flow better to refer to the expression that provides the handler value as the "tag" and hence we would say a "tagged template string".
I don't have anything invested in any of this terminology, so I'd happy to adjust it for something that is clearer to users.
let tmpl = addresses => html
<table> ${addresses.forEach(address=> html
<tr>${address.first}</tr><tr>${address.last}</tr>).join('\n') } </table>
would be my guess? Similarly for the localization example in the blog post: arrow functions should make it relatively painless to make the template parameters explicit.
Of course, building HTML from nested templates is not the same as filling a flat HTML template with user input, so I'm not sure what the implicit encoding of template parameters will do to this approach.
Nice. I’d let the html handler do the join, then it’s even shorter. That is: If a substitution is an array of strings, it joins, otherwise it coerces to string.
let tmpl = addresses => html
<table> ${addresses.forEach(address=> html
<tr>${address.first}</tr><tr>${address.last}</tr>).join('\n') } </table>
Yes. But you need to say ".map(" rather than ".forEach(" above. See harmony:quasis#nesting.
Oops, yes!
Thanks for pointing out how much fat arrows help for this use case. I knew it would help but hadn't expected it to help that much. Nice!
Anything that helps to convince people that arrow functions are not just an odd way of writing functions for people who don't like to type;-)
Btw, the negative experience with Haskell's "monads" terminology shows that choosing a scary name can hamper the adoption of even the most useful language features. So switching to "template strings" is a good idea. We do need to communicate that they are not limited to strings, though: template parameters and tag results can be arbitrary ES objects/values.
Claus
On Aug 3, 2012, at 1:08 PM, Claus Reinke wrote:
Btw, the negative experience with Haskell's "monads" terminology shows that choosing a scary name can hamper the adoption of even the most useful language features. So switching to "template strings" is a good idea. We do need to communicate that they are not limited to strings, though: template parameters and tag results can be arbitrary ES objects/values.
I chose "template string" over "string template" to emphasize that it was a template that was expressed as a string rather than a template for a string. That may be too subtle of a distinction. At the TC39 there were some concerns that simply "template" was too general and might cause confusion relative to other templating mechanism.
Not sure that something better than “template string” exists. It would have to be something that describes the construct well: It is an interesting hybrid between a literal (such as a regular expression) and a function call.
Ah, OK. Spitballing: A synonym of tag then, maybe? Alas, label is out. If the term was, say, “mark” then one could conceivably say “mark function” instead of handler.
On Fri, Aug 3, 2012 at 10:30 PM, Axel Rauschmayer <axel at rauschma.de> wrote:
Ah, OK. Spitballing: A synonym of tag then, maybe? Alas, label is out. If the term was, say, “mark” then one could conceivably say “mark function” instead of handler.
Aren't these macros?
tagliteral${substitution}literal
macroliteral${substitution}literal
The default or passthru macro applies when the developer does not supply a macro.
Or if you prefer
macro_functiona macro with ${substitution} here
Then we don't have to spend several years explaining how template strings are templates but not <template>s and aren't string templates because they
take non-string substitutions.
(IMO oxymoronic quasi-literal is embarrassing).
jjb
It is a matter of definition and taste, but I don't think it is useful to think of these as macros. I expect macros to extend the base language as if adding new special forms, where these special forms are stylistically similar to the existing special forms. For example
myfor (x of xs) { print(x); } between { print(','); }
or
expr ||| expr
For quasi-literals, first, I agree that "quasi" anything is not a good choice and that "string template" is better. The suggested analogy to other things called templates seems more useful. But best I think would be terminology that suggests that this is a generic DSL embedding mechanism, where you can escape back into the host language from holes in the guest language. The thing to the left of the first backquote, more than anything else names the guest language being embedded. (FWIW, in E we call in It the quasiparser ;).)
Mark Miller wrote:
For quasi-literals, first, I agree that "quasi" anything is not a good choice and that "string template" is better.
s/string template/template string/ ;-)
Perhaps “string template” would actually be better than “template string”: “template” makes sense as “something to fill in” (that is not a string, because it can be highly structured, via nesting etc.) and “string” makes sense, because the blanks to fill in are surrounded by strings. The only thing that leads one astray is that templates normally only produce text in the web dev world.
Following the DSL idea, another possibility is:
- quasi literal = domain literal
- quasi literal tag = domain name
- tagged quasi literal = named domain literal
- untagged quasi literal = anonymous domain literal
- quasi handler = domain handler
Again, playing devil’s advocate, I don’t mind “template string”.
On Sat, Aug 4, 2012 at 1:22 PM, Mark Miller <erights at gmail.com> wrote:
It is a matter of definition and taste, but I don't think it is useful to think of these as macros. I expect macros to extend the base language as if adding new special forms, where these special forms are stylistically similar to the existing special forms. For example
myfor (x of xs) { print(x); } between { print(','); }
or
expr ||| expr
Such a macro capability would go quite beyond what most practitioners imagine when they hear 'macro'. I guess they imagine either C macros or "a scripting language".
For quasi-literals, first, I agree that "quasi" anything is not a good choice and that "string template" is better. The suggested analogy to other things called templates seems more useful. But best I think would be terminology that suggests that this is a generic DSL embedding mechanism, where you can escape back into the host language from holes in the guest language.
You just made the argument that this feature is so limited that it isn't a generic DSL embedding mechanism. Really the 'DSL' syntax here is much closer to clunky MACRO() than to "embedded language". However I like the mental image you give in "embedding mechanism, where you can escape back into the host language from holes in the guest language." Maybe more descriptions will help a better name emerge. Here is my try:
The feature combines a new string-definition syntax with a new function-calling syntax. Backticks are quotes with multi-line powers and they are parens for the new function calls; $/${} supplants comma as an argument separator. The functions called with backticks always receive an array argument with odd length and elements that alternate between strings and values.
That makes me think 'template'. However 'string template' for me generates strings; and 'template string' is redundant by repeating itself. (On the other hand, this feature without strings would just a silly way to call a function).
Another direction: Joe Hewitt's system for generating the Firebug UI was 'domplate', an invented word that use 'plate' to evoke 'template' and 'dom' since it generated DOM elements. Since this feature is not limited to DOM elements, maybe combine 'plate' with another noun to identify the kind of template here. "Backplate" anyone?
jjb
need to communicate that they are not limited to strings, though: template parameters and tag results can be arbitrary ES objects/values.
I chose "template string" over "string template" to emphasize that it was a template that was expressed as a string rather than a template for a string. That may be too subtle of a distinction. At the TC39 there were some concerns that simply "template" was too general and might cause confusion relative to other templating mechanism.
The naming distinction is too subtle, but the "template is a string" explanation applies to both versions. I was not asking for more name bikeshedding, and the initial applications seem to be for generating strings.
It might be sufficient if tutorials involving template strings would feature at least one example with non-string result and arguments, to indicate that there is more to them.
Hmm, I see myself wanting to refer to the strings involved in a template, and I wouldn't want to talk about "template string strings".
We could also try to accompany the name with a concise description.
ES6 tagged template:
A template string, filled with expression parameters, result
depends on the tag handler (function) consuming both.
Claus
What exactly is being accomplished with tagged templates? I mean, what is
the use case? It seems to make certain specific function calls look very
different from a typical function call, the arguments passed in are not
very clearly explained in the draft or wiki, and I have difficulty
imagining anyone actually using these for anything. I would love to hear a
solid case for these (I've been looking for the past few nights, but
nothing has shown up). Template literals are great, but the tagging
thing
seems fishy for the vast majority of applications.
I'm not saying they shouldn't be included in harmony, i'm just very interested in finding out what practical task they are meant to accomplish
- Regular expressions
- Escaping the variable parts of domain-specific languages
- HTML templates (think Facebook’s React)
- Internationalization
On the point of DLS's, are there any example points like the regex one you posted Axel? I'm curious as to how you would do the transform
How about:
cs = require('coffee-script').compile;
eval(cs`
gcd = (x,y) -> [x,y] = [y,x%y] until y is 0; x
`);
Presumably coffee-script counts as a (large!) DSL.
Tagged template strings are one of my favorite parts of ES6. I include them and generators in my "ES6 The Awesome Parts" talk.
Sample uses from that slide deck, most of them cribbed from the wiki:
// Contextual auto-escaping
qsa`.${className}`;
safehtml`<a href="${url}?q=${query}" onclick="alert('${message}')" style="color: ${color}">${message}</a>`;
// Localization and formatting
l10n`Hello ${name}; you are visitor number ${visitor}:n! You have ${money}:c in your account!`
// Regexes
re`\d+${separator}\d+`
// Embedded HTML/XML
jsx`<a href="${url}">${text}</a>` // becomes React.DOM.a({ href: url }, text)
// DSLs for code execution
var childProcess = sh`ps ax | grep ${pid}`;
var xhr = POST`http://example.org/service?a=${a}&b=${b}
Content-Type: application/json
Authorization: ${credentials}
{ "foo": ${foo}, "bar": ${bar} }`;
On Mar 6, 2014, at 15:46 , Axel Rauschmayer <axel at rauschma.de> wrote:
- Internationalization
Not internationalization. The strawman page for template strings (quasi-literals back then) included some ideas for how they might be used for internationalization and localization, but internationalization generally doesn't allow localizable strings to be embedded in source code (specialized environments like Closure may be an exception). In addition, message formatting has requirements that cannot be addressed with template strings - for example, gender support may require additional variables to be provided that are only used in some languages, not in others, but template strings don't provide a way to pass unused variables:
On Mar 6, 2014, at 18:51 , Domenic Denicola <domenic at domenicdenicola.com> wrote:
// Localization and formatting l10n
Hello ${name}; you are visitor number ${visitor}:n! You have ${money}:c in your account!
A correct German translation of this would have to take the gender of the visitor into consideration:
- Male:
l10n`Hallo, Herr ${name}; Sie sind Besucher Nummer ${visitor}:n. Sie haben ${money}:c auf Ihrem Konto.`
- Female:
l10n`Hallo, Frau ${name}; Sie sind Besucherin Nummer ${visitor}:n. Sie haben ${money}:c auf Ihrem Konto.`
How would you do that with template strings?
How would you do that with template strings?
The English version could be used as a key to look up the international version. You could also reorder the pieces. A bit of work for a library, but template strings would help, a little.
I wish I could just link to Google's internal i18n course material to give an idea of how far, far, far more difficult this problem is. Template strings are rather a distraction in that space.
On Mar 6, 2014, at 23:40 , Axel Rauschmayer <axel at rauschma.de> wrote:
The English version could be used as a key to look up the international version. You could also reorder the pieces. A bit of work for a library, but template strings would help, a little.
If by "used as a key" you mean something like the last part of harmony:quasis#message_replacement_and_substitution_re-ordering then I don't see what value the template strings provide here over just using a simple substitution function. And it appears you lose the ability to use meaningful variable names in the resource bundles.
You haven't addressed how to solve the gender problem.
Has anybody actually implemented a complete msg/l10n function for template strings that provides the functionality of, say, MessageFormat and ResourceBundle in ICU, and used it in a real internationalization and localization project?
It seems to me that the main benefit is that it takes care of parsing out the template parts around the expressions for you. Otherwise you might write a regular expression to do that.
I love the new name “template strings” for “quasi literals”. Only “tag” seem inferior to “quasi handler”, because that former term is already used in HTML.
Template strings are not ideally suited for templates (think Mustache), as expressed by Nicholas Zakas [1]. Any ideas for helping here? The best I can come up with is:
Custom syntax: The dollar sign ($) starts a command. As substitutions always have to be in curly braces, that doesn’t clash with template string syntax.
This could be OK for quick and dirty templates stored inside source code, with the advantage of the ES.next parser handling nesting for you.
[1] www.nczonline.net/blog/2012/08/01/a-critical-review-of-ecmascript-6-quasi-literals