String identity template tag

T.J. Crowder tj.crowder at
Fri Dec 14 09:13:36 UTC 2018

On Thu, Dec 13, 2018 at 7:00 PM Mark Miller
<erights at> wrote:
> As for the optional mapping function, there's nothing about that
> which is more relevant to cooked base strings than to raw base
> strings. We should be able to apply mapping functions to either,
> as well as to other base tags, in a similar way. This suggests
> tag combinators...

Probably as a separate thing? Since `cook`/`cooked`/`interpolate` isn't
primarily a tag function.

> As a completely separate point, this way of escaping html is not
> context sensitive, and likely horribly unsafe.

It was just a throwaway for the example, for the specific context of using
the string within the body of a tag (not in attribute text, etc.). Correct
me if I'm wrong, but for that context, I believe it's sufficient.

> In this case, if we choose a name like "cook" or "cooked" in order
> to make the analogy with String.raw, then it should have the same
> API surface as String.raw.

Sadly, yes. I say "sadly" because I quite liked `cook` (or `cooked`), but
only for frivolous reasons. :-)

+1 for Allen's `String.interpolate`. Something along these lines, accepting
array-likes rather than iterables (though that's a discussion to have):

const toLength = n => {
    n = Math.min(+n || 0, Number.MAX_SAFE_INTEGER);
    return n < 0 ? Math.ceil(n) : Math.floor(n);
Object.defineProperty(String, "interpolate", {
    value(strings, subs = [], mapFn) {
        const strslen = toLength(strings.length);
        if (strslen <= 0) {
            return "";
        const subslen = toLength(subs.length);
        let s = "";
        let index = 0;
        while (true) {
            const subIndex = index;
            s += strings[index++];
            if (index == strslen) {
                return s;
            if (subIndex < subslen) {
                const sub = subs[subIndex];
                s += mapFn ? mapFn(sub) : sub;
    configurable: true,
    writable: true


Like `String.raw`, that ignores entries in `subs` at or after
`strings.length - 1`. (It's basically `String.raw`'s algorithm, and like
`raw`'s algorithm, it's un-optimized for clarity.) But that's also a
discussion to have, perhaps it should tack them on the end. It won't come
up in the simple use case of passing along the strings and subs in a tag
function (`subs` will always have one fewer entry than `strings`), but it's
slightly more general-purpose if it tacks them on the end.

`String.interpolate` would also fit nicely if at some stage there were an
`Array.interpolate` (e.g., "zip").

-- T.J. Crowder
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list