String identity template tag

Mike Samuel mikesamuel at gmail.com
Fri Dec 14 19:03:53 UTC 2018


On Fri, Dec 14, 2018 at 12:51 PM Isiah Meadows <isiahmeadows at gmail.com>
wrote:

> I'll point out Kai could be on to something, although I disagree `zip`
> would be the right abstraction. Maybe `Array.interleave(...arrays)`? You
> could do `Array.interleave(template, args).map(String).join("")` for
> similar effect, and it'd be more generally useful.
>
> The key here is that iteration would stop after the index hits any array's
> length, so it'd be polyfilled kinda like this:
>
> ```js
> Array.interpolate = (...args) => {
>     let ret = []
>     let lengths = []
>     let count = 0
>     for (let i = 0; i < args.length; i++) {
>         lengths[i] = args[i].count
>     }
>     for (let index = 0; ; index++) {
>         for (let i = 0; i < args.length; i++) {
>             if (index === lengths[i]) return ret
>             ret[count++] = args[i][index]
>         }
>     }
> }
> ```
>
> (This could be optimized, though.)
>

As a data point, something like this loop appears in most of the template
tags I've written but
it's never had these precise semantics so I didn't bother putting it into
template-tag-common <https://www.npmjs.com/package/template-tag-common>.

That library makes it easy to split the operation of a template tag into 3
stages:
1. An optional configuration stage accessed by calling the template tag as
a regular function: mytag({ /* options */)`...`
2. Static analysis over the strings.   This is memoized.
3. Computing a result from (options, strings, results of step 2,
interoplated values)

The final loop (step 3) in the template tags I maintain tends to looks like

function computeResult(options, staticState /* from step 2 */, strings,
...values) {
  let n = values.length;  // Could do Math.max(strings.length - 1,
values.length);
  let result = strings[0];  // Usually strings.raw
  for (let i = 0; i < n;) {
    const interpolatedValue = f(options, staticState[i], values[i]);
    // Sometimes code here looks backwards at the result to see if it needs
to avoid token-merging hazards.
    result += interpolatedValue;
    result += strings[++i];
  }
  return wrapResult(result);  // Produce a value of a type that
encapsulates the tag's security guarantees.
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20181214/b50a528e/attachment-0001.html>


More information about the es-discuss mailing list