Proposal: Symbol.templateTag
I have run into this myself. It is a real problem, and I like the nature of your proposed solution. But I don't understand how it might break the web. If Symbol.templateTag is a new symbol, guaranteed unequal to any prior value, how can introducing it, and new behavior conditional on it, change any existing behavior?
Hi Alexander, I have run into this myself. It is a real problem, and I like
the nature of your proposed solution. But I don't understand how it might
break the web. If Symbol.templateTag is a new symbol, guaranteed unequal to
any prior value, how can introducing it, and new behavior conditional on
it, change any existing behavior?
On Wed, Nov 16, 2016 at 5:02 PM, Alexander Jones <alex at weej.com> wrote:
> Hi es-discuss!
>
> Template tags are a great feature with many novel applications, IMO
> approaching macro-level expressiveness. But due to their nature in this
> context, it's helpful if tags are named quite tersely. Unfortunately, if
> you have existing API, this can be challenging.
>
> Let's say I have a DSL (domain-specific language), and I *may*, unsafely,
> generate typed snippets of code containing that DSL like so:
>
> ```js
> function dsl(code: string) {
> // `code` MUST be well-formed
> }
>
> const someStatement = dsl("val foo = " + dslEncode(foo));
> ```
>
> Let's say I'd like to add support in my library for ES6 clients such that
> they can do:
>
> ```js
> const someStatement = dsl`val foo = ${foo}`;
> ```
>
> where the `dsl` template tag would be implemented such that `dslEncode` is
> used on each interpolated expression.
>
> Unfortunately, the `dsl` function's arguments are already defined and
> can't be changed. I'd need a new name, like `dsl.tag`, which would end up
> being a fair bit more verbose.
>
> Would it be possible, at this point, to introduce a new behaviour into ES
> such that instead of merely calling the tag object, the implementation
> first checks for a `Symbol.templateTag` property on the tag object, and if
> it exists, it is invoked? I'd guess this can't Break The Web because no-one
> can realistically be using an existing function as a template tag if it was
> not already designed for it.
>
> ```js
> const someStatement = dsl`val foo = ${foo}`;
> // desugars to, approximately
> const someStatement = (dsl[Symbol.templateTag] || dsl)(["val foo =", ""],
> foo);
> ```
>
> To be honest, I am kind of surprised it wasn't already implemented like
> this, but maybe there were performance concerns with the branching.
> Interested in your thoughts.
>
> Thanks
>
> Alex
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
--
Cheers,
--MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20161116/c5878d87/attachment.html>OK, I was thinking about this incorrectly and I think you're right - it doesn't Break The Web. It's exactly the same as when @@isConcatSpreadable and @@toStringTag were introduced, as far as I can tell.
If no-one has any obvious objections to save me the effort, I'll try to write up a stage 0 this weekend.
OK, I was thinking about this incorrectly and I think you're right - it
doesn't Break The Web. It's exactly the same as when @@isConcatSpreadable
and @@toStringTag were introduced, as far as I can tell.
If no-one has any obvious objections to save me the effort, I'll try to
write up a stage 0 this weekend.
Thanks
On 17 November 2016 at 04:58, Mark S. Miller <erights at google.com> wrote:
> Hi Alexander, I have run into this myself. It is a real problem, and I
> like the nature of your proposed solution. But I don't understand how it
> might break the web. If Symbol.templateTag is a new symbol, guaranteed
> unequal to any prior value, how can introducing it, and new behavior
> conditional on it, change any existing behavior?
>
>
>
>
> On Wed, Nov 16, 2016 at 5:02 PM, Alexander Jones <alex at weej.com> wrote:
>
>> Hi es-discuss!
>>
>> Template tags are a great feature with many novel applications, IMO
>> approaching macro-level expressiveness. But due to their nature in this
>> context, it's helpful if tags are named quite tersely. Unfortunately, if
>> you have existing API, this can be challenging.
>>
>> Let's say I have a DSL (domain-specific language), and I *may*, unsafely,
>> generate typed snippets of code containing that DSL like so:
>>
>> ```js
>> function dsl(code: string) {
>> // `code` MUST be well-formed
>> }
>>
>> const someStatement = dsl("val foo = " + dslEncode(foo));
>> ```
>>
>> Let's say I'd like to add support in my library for ES6 clients such that
>> they can do:
>>
>> ```js
>> const someStatement = dsl`val foo = ${foo}`;
>> ```
>>
>> where the `dsl` template tag would be implemented such that `dslEncode`
>> is used on each interpolated expression.
>>
>> Unfortunately, the `dsl` function's arguments are already defined and
>> can't be changed. I'd need a new name, like `dsl.tag`, which would end up
>> being a fair bit more verbose.
>>
>> Would it be possible, at this point, to introduce a new behaviour into ES
>> such that instead of merely calling the tag object, the implementation
>> first checks for a `Symbol.templateTag` property on the tag object, and if
>> it exists, it is invoked? I'd guess this can't Break The Web because no-one
>> can realistically be using an existing function as a template tag if it was
>> not already designed for it.
>>
>> ```js
>> const someStatement = dsl`val foo = ${foo}`;
>> // desugars to, approximately
>> const someStatement = (dsl[Symbol.templateTag] || dsl)(["val foo =", ""],
>> foo);
>> ```
>>
>> To be honest, I am kind of surprised it wasn't already implemented like
>> this, but maybe there were performance concerns with the branching.
>> Interested in your thoughts.
>>
>> Thanks
>>
>> Alex
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
> --
> Cheers,
> --MarkM
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20161118/c936f970/attachment.html>I'm not fully sure I understand ... instead of:
const dsl = (chunks, ...rest) => chunks.reduce((s, c, i) => s + (i ?
rest[i-1] : '') + c);
you are looking for something similar ?
const dsl = (chunks, ...rest) => chunks.reduce((s, c, i) => s + (
i ? (dsl[Symbol.templateTag] || String)(rest[i-1]) : ''
) + c);
if that's the case, is Symbol.templateTag really needed ?
It looks to me it's possible to define your own behavior through your own transformer already and this proposal easily brings parsing-method clashing in the plate.
Or maybe not ... like I've said, I haven't fully understood the issue.
Thanks for any sort of extra clarification.
I'm not fully sure I understand ... instead of:
```js
const dsl = (chunks, ...rest) => chunks.reduce((s, c, i) => s + (i ?
rest[i-1] : '') + c);
```
you are looking for something similar ?
```js
const dsl = (chunks, ...rest) => chunks.reduce((s, c, i) => s + (
i ? (dsl[Symbol.templateTag] || String)(rest[i-1]) : ''
) + c);
```
if that's the case, is `Symbol.templateTag` really needed ?
It looks to me it's possible to define your own behavior through your own
transformer already and this proposal easily brings parsing-method clashing
in the plate.
Or maybe not ... like I've said, I haven't fully understood the issue.
Thanks for any sort of extra clarification.
Regards
On Fri, Nov 18, 2016 at 12:30 AM, Alexander Jones <alex at weej.com> wrote:
> OK, I was thinking about this incorrectly and I think you're right - it
> doesn't Break The Web. It's exactly the same as when @@isConcatSpreadable
> and @@toStringTag were introduced, as far as I can tell.
>
> If no-one has any obvious objections to save me the effort, I'll try to
> write up a stage 0 this weekend.
>
> Thanks
>
>
>
> On 17 November 2016 at 04:58, Mark S. Miller <erights at google.com> wrote:
>
>> Hi Alexander, I have run into this myself. It is a real problem, and I
>> like the nature of your proposed solution. But I don't understand how it
>> might break the web. If Symbol.templateTag is a new symbol, guaranteed
>> unequal to any prior value, how can introducing it, and new behavior
>> conditional on it, change any existing behavior?
>>
>>
>>
>>
>> On Wed, Nov 16, 2016 at 5:02 PM, Alexander Jones <alex at weej.com> wrote:
>>
>>> Hi es-discuss!
>>>
>>> Template tags are a great feature with many novel applications, IMO
>>> approaching macro-level expressiveness. But due to their nature in this
>>> context, it's helpful if tags are named quite tersely. Unfortunately, if
>>> you have existing API, this can be challenging.
>>>
>>> Let's say I have a DSL (domain-specific language), and I *may*,
>>> unsafely, generate typed snippets of code containing that DSL like so:
>>>
>>> ```js
>>> function dsl(code: string) {
>>> // `code` MUST be well-formed
>>> }
>>>
>>> const someStatement = dsl("val foo = " + dslEncode(foo));
>>> ```
>>>
>>> Let's say I'd like to add support in my library for ES6 clients such
>>> that they can do:
>>>
>>> ```js
>>> const someStatement = dsl`val foo = ${foo}`;
>>> ```
>>>
>>> where the `dsl` template tag would be implemented such that `dslEncode`
>>> is used on each interpolated expression.
>>>
>>> Unfortunately, the `dsl` function's arguments are already defined and
>>> can't be changed. I'd need a new name, like `dsl.tag`, which would end up
>>> being a fair bit more verbose.
>>>
>>> Would it be possible, at this point, to introduce a new behaviour into
>>> ES such that instead of merely calling the tag object, the implementation
>>> first checks for a `Symbol.templateTag` property on the tag object, and if
>>> it exists, it is invoked? I'd guess this can't Break The Web because no-one
>>> can realistically be using an existing function as a template tag if it was
>>> not already designed for it.
>>>
>>> ```js
>>> const someStatement = dsl`val foo = ${foo}`;
>>> // desugars to, approximately
>>> const someStatement = (dsl[Symbol.templateTag] || dsl)(["val foo =",
>>> ""], foo);
>>> ```
>>>
>>> To be honest, I am kind of surprised it wasn't already implemented like
>>> this, but maybe there were performance concerns with the branching.
>>> Interested in your thoughts.
>>>
>>> Thanks
>>>
>>> Alex
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>
>>
>> --
>> Cheers,
>> --MarkM
>>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20161118/85d53a51/attachment.html>fix: forgot of course i would never be 0
`const dsl = (chunks, ...rest) => chunks.reduce((s, c, i) => s + rest[i-1]
- c);`
VS
const dsl = (chunks, ...rest) => chunks.reduce((s, c, i) => s + (dsl[Symbol.templateTag] || String)(rest[i-1]) + c);
fix: forgot of course i would never be 0
`const dsl = (chunks, ...rest) => chunks.reduce((s, c, i) => s + rest[i-1]
+ c);`
VS
`const dsl = (chunks, ...rest) => chunks.reduce((s, c, i) => s +
(dsl[Symbol.templateTag]
|| String)(rest[i-1]) + c);`
On Fri, Nov 18, 2016 at 12:56 AM, Andrea Giammarchi <
andrea.giammarchi at gmail.com> wrote:
> I'm not fully sure I understand ... instead of:
>
> ```js
> const dsl = (chunks, ...rest) => chunks.reduce((s, c, i) => s + (i ?
> rest[i-1] : '') + c);
> ```
>
> you are looking for something similar ?
>
> ```js
> const dsl = (chunks, ...rest) => chunks.reduce((s, c, i) => s + (
> i ? (dsl[Symbol.templateTag] || String)(rest[i-1]) : ''
> ) + c);
> ```
>
> if that's the case, is `Symbol.templateTag` really needed ?
>
> It looks to me it's possible to define your own behavior through your own
> transformer already and this proposal easily brings parsing-method clashing
> in the plate.
>
> Or maybe not ... like I've said, I haven't fully understood the issue.
>
> Thanks for any sort of extra clarification.
>
> Regards
>
>
> On Fri, Nov 18, 2016 at 12:30 AM, Alexander Jones <alex at weej.com> wrote:
>
>> OK, I was thinking about this incorrectly and I think you're right - it
>> doesn't Break The Web. It's exactly the same as when @@isConcatSpreadable
>> and @@toStringTag were introduced, as far as I can tell.
>>
>> If no-one has any obvious objections to save me the effort, I'll try to
>> write up a stage 0 this weekend.
>>
>> Thanks
>>
>>
>>
>> On 17 November 2016 at 04:58, Mark S. Miller <erights at google.com> wrote:
>>
>>> Hi Alexander, I have run into this myself. It is a real problem, and I
>>> like the nature of your proposed solution. But I don't understand how it
>>> might break the web. If Symbol.templateTag is a new symbol, guaranteed
>>> unequal to any prior value, how can introducing it, and new behavior
>>> conditional on it, change any existing behavior?
>>>
>>>
>>>
>>>
>>> On Wed, Nov 16, 2016 at 5:02 PM, Alexander Jones <alex at weej.com> wrote:
>>>
>>>> Hi es-discuss!
>>>>
>>>> Template tags are a great feature with many novel applications, IMO
>>>> approaching macro-level expressiveness. But due to their nature in this
>>>> context, it's helpful if tags are named quite tersely. Unfortunately, if
>>>> you have existing API, this can be challenging.
>>>>
>>>> Let's say I have a DSL (domain-specific language), and I *may*,
>>>> unsafely, generate typed snippets of code containing that DSL like so:
>>>>
>>>> ```js
>>>> function dsl(code: string) {
>>>> // `code` MUST be well-formed
>>>> }
>>>>
>>>> const someStatement = dsl("val foo = " + dslEncode(foo));
>>>> ```
>>>>
>>>> Let's say I'd like to add support in my library for ES6 clients such
>>>> that they can do:
>>>>
>>>> ```js
>>>> const someStatement = dsl`val foo = ${foo}`;
>>>> ```
>>>>
>>>> where the `dsl` template tag would be implemented such that `dslEncode`
>>>> is used on each interpolated expression.
>>>>
>>>> Unfortunately, the `dsl` function's arguments are already defined and
>>>> can't be changed. I'd need a new name, like `dsl.tag`, which would end up
>>>> being a fair bit more verbose.
>>>>
>>>> Would it be possible, at this point, to introduce a new behaviour into
>>>> ES such that instead of merely calling the tag object, the implementation
>>>> first checks for a `Symbol.templateTag` property on the tag object, and if
>>>> it exists, it is invoked? I'd guess this can't Break The Web because no-one
>>>> can realistically be using an existing function as a template tag if it was
>>>> not already designed for it.
>>>>
>>>> ```js
>>>> const someStatement = dsl`val foo = ${foo}`;
>>>> // desugars to, approximately
>>>> const someStatement = (dsl[Symbol.templateTag] || dsl)(["val foo =",
>>>> ""], foo);
>>>> ```
>>>>
>>>> To be honest, I am kind of surprised it wasn't already implemented like
>>>> this, but maybe there were performance concerns with the branching.
>>>> Interested in your thoughts.
>>>>
>>>> Thanks
>>>>
>>>> Alex
>>>>
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> es-discuss at mozilla.org
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>
>>>>
>>>
>>>
>>> --
>>> Cheers,
>>> --MarkM
>>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20161118/b8766376/attachment-0001.html>As promised (to myself!) I've written a stage-0.
alex-weej/es-symbol-template-tag
Your feedback is greatly appreciated.
As promised (to myself!) I've written a stage-0.
https://github.com/alex-weej/es-symbol-template-tag
Your feedback is greatly appreciated.
Thanks
On 18 November 2016 at 00:30, Alexander Jones <alex at weej.com> wrote:
> OK, I was thinking about this incorrectly and I think you're right - it
> doesn't Break The Web. It's exactly the same as when @@isConcatSpreadable
> and @@toStringTag were introduced, as far as I can tell.
>
> If no-one has any obvious objections to save me the effort, I'll try to
> write up a stage 0 this weekend.
>
> Thanks
>
>
>
> On 17 November 2016 at 04:58, Mark S. Miller <erights at google.com> wrote:
>
>> Hi Alexander, I have run into this myself. It is a real problem, and I
>> like the nature of your proposed solution. But I don't understand how it
>> might break the web. If Symbol.templateTag is a new symbol, guaranteed
>> unequal to any prior value, how can introducing it, and new behavior
>> conditional on it, change any existing behavior?
>>
>>
>>
>>
>> On Wed, Nov 16, 2016 at 5:02 PM, Alexander Jones <alex at weej.com> wrote:
>>
>>> Hi es-discuss!
>>>
>>> Template tags are a great feature with many novel applications, IMO
>>> approaching macro-level expressiveness. But due to their nature in this
>>> context, it's helpful if tags are named quite tersely. Unfortunately, if
>>> you have existing API, this can be challenging.
>>>
>>> Let's say I have a DSL (domain-specific language), and I *may*,
>>> unsafely, generate typed snippets of code containing that DSL like so:
>>>
>>> ```js
>>> function dsl(code: string) {
>>> // `code` MUST be well-formed
>>> }
>>>
>>> const someStatement = dsl("val foo = " + dslEncode(foo));
>>> ```
>>>
>>> Let's say I'd like to add support in my library for ES6 clients such
>>> that they can do:
>>>
>>> ```js
>>> const someStatement = dsl`val foo = ${foo}`;
>>> ```
>>>
>>> where the `dsl` template tag would be implemented such that `dslEncode`
>>> is used on each interpolated expression.
>>>
>>> Unfortunately, the `dsl` function's arguments are already defined and
>>> can't be changed. I'd need a new name, like `dsl.tag`, which would end up
>>> being a fair bit more verbose.
>>>
>>> Would it be possible, at this point, to introduce a new behaviour into
>>> ES such that instead of merely calling the tag object, the implementation
>>> first checks for a `Symbol.templateTag` property on the tag object, and if
>>> it exists, it is invoked? I'd guess this can't Break The Web because no-one
>>> can realistically be using an existing function as a template tag if it was
>>> not already designed for it.
>>>
>>> ```js
>>> const someStatement = dsl`val foo = ${foo}`;
>>> // desugars to, approximately
>>> const someStatement = (dsl[Symbol.templateTag] || dsl)(["val foo =",
>>> ""], foo);
>>> ```
>>>
>>> To be honest, I am kind of surprised it wasn't already implemented like
>>> this, but maybe there were performance concerns with the branching.
>>> Interested in your thoughts.
>>>
>>> Thanks
>>>
>>> Alex
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>
>>
>> --
>> Cheers,
>> --MarkM
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20161120/521821c0/attachment.html>
discuss!
Template tags are a great feature with many novel applications, IMO approaching macro-level expressiveness. But due to their nature in this context, it's helpful if tags are named quite tersely. Unfortunately, if you have existing API, this can be challenging.
Let's say I have a DSL (domain-specific language), and I may, unsafely, generate typed snippets of code containing that DSL like so:
function dsl(code: string) { // `code` MUST be well-formed } const someStatement = dsl("val foo = " + dslEncode(foo));Let's say I'd like to add support in my library for ES6 clients such that they can do:
const someStatement = dsl`val foo = ${foo}`;where the
dsltemplate tag would be implemented such thatdslEncodeis used on each interpolated expression.Unfortunately, the
dslfunction's arguments are already defined and can't be changed. I'd need a new name, likedsl.tag, which would end up being a fair bit more verbose.Would it be possible, at this point, to introduce a new behaviour into ES such that instead of merely calling the tag object, the implementation first checks for a
Symbol.templateTagproperty on the tag object, and if it exists, it is invoked? I'd guess this can't Break The Web because no-one can realistically be using an existing function as a template tag if it was not already designed for it.const someStatement = dsl`val foo = ${foo}`; // desugars to, approximately const someStatement = (dsl[Symbol.templateTag] || dsl)(["val foo =", ""], foo);To be honest, I am kind of surprised it wasn't already implemented like this, but maybe there were performance concerns with the branching. Interested in your thoughts.
Thanks
Alex
Hi es-discuss! Template tags are a great feature with many novel applications, IMO approaching macro-level expressiveness. But due to their nature in this context, it's helpful if tags are named quite tersely. Unfortunately, if you have existing API, this can be challenging. Let's say I have a DSL (domain-specific language), and I *may*, unsafely, generate typed snippets of code containing that DSL like so: ```js function dsl(code: string) { // `code` MUST be well-formed } const someStatement = dsl("val foo = " + dslEncode(foo)); ``` Let's say I'd like to add support in my library for ES6 clients such that they can do: ```js const someStatement = dsl`val foo = ${foo}`; ``` where the `dsl` template tag would be implemented such that `dslEncode` is used on each interpolated expression. Unfortunately, the `dsl` function's arguments are already defined and can't be changed. I'd need a new name, like `dsl.tag`, which would end up being a fair bit more verbose. Would it be possible, at this point, to introduce a new behaviour into ES such that instead of merely calling the tag object, the implementation first checks for a `Symbol.templateTag` property on the tag object, and if it exists, it is invoked? I'd guess this can't Break The Web because no-one can realistically be using an existing function as a template tag if it was not already designed for it. ```js const someStatement = dsl`val foo = ${foo}`; // desugars to, approximately const someStatement = (dsl[Symbol.templateTag] || dsl)(["val foo =", ""], foo); ``` To be honest, I am kind of surprised it wasn't already implemented like this, but maybe there were performance concerns with the branching. Interested in your thoughts. Thanks Alex -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20161117/2113da66/attachment.html>