tc39 / proposal-string-cooked

ECMAScript proposal for String.cooked built-in template tag

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Name bikeshed

jamiebuilds opened this issue · comments

Splitting this out from #1 cause this tends to be a big topic.

options:

String.cooked

The primary appeal of this is to contrast it against String.raw. A potential downside to that name is that it doesn't really match the intended use case of this function: To make it easier to implement "value pre-processing" tagged template functions.

String.interpolate

This function aligns a bit more with the intended usage of this function, and is overall a bit more literal about what it does internally.

String.identity

This name has been brought up before, it refers to the fact that these two are equivalent:

let a = String.identity`tag`
let b = `tag`

The downside is that using this function as the direct tag of a tagged template is not really its intended use case, and calling it within another tag makes it a somewhat weird name.

Other names

Feel free to suggest other names, but if you do, please explain what that name accomplishes and what it loses out on from the other names already suggested.

+1 for String.cooked.

On reflection, I also like String.interpolate. Sorry to be unhelpful!

Pro for String.identity is that if you're doing something that's meant to take a tag function (and which will then call the function on a template string at some point), identity immediately suggests its role as a default/no-op value; none of the other names do. Con is that it suggests you'll get the exact string you put in if there is no interpolation, which isn't true - the escapes are resolved.

I quite like cooked. It's a little silly, but it has several good points for it:

  • The obvious connection between "raw" and "cooked" suggests they're doing nearly the same thing, which is correct.
  • The meaning of "cooked" hints toward the transformation of the literal segments into their final (escapes resolved) form; the word "cooked" is used in this way in other programming contexts sometimes.

Not a fan of interpolate - all tag functions interpolate (assuming you're referring to the ${} segments). The important notion to capture here is what it does to the literal segments, vs raw.

Since you're looking to match the behaviour of an untagged template, why not something like String.asIfUntagged or just String.untagged? It can be thought of as the "implicit tag" for a template when one isn't provided.

In a recent refactoring of TV and TRV, we chose to refer to the cooked properties as the "indexed components" of the template (since the only reference to the term "cooked" currently is in alias names), in contrast to the "raw components". Though I think String.indexed doesn't really do the job here.

I am fine with either of String.interpolate or String.identity. I would avoid String.cooked since, as mentioned above, it's not normatively referenced or defined in the spec, and the usage of the term seems to be TC39-internal.

I would avoid String.cooked since, as mentioned above, it's not normatively referenced or defined in the spec, and the usage of the term seems to be TC39-internal.

raw is in the language, and cooked is an obvious analogue to raw which suggests precisely the behavior it has.

I had no idea we even used the term "cooked" internally in the spec. It just sounds like a nice analogue, and lightly conveys the precise meaning intended here - the string pieces have been allowed to "mature" and change to their final forms.

One downside for names like String.zip, String.interleave, possibly String.interpolate, and arguably String.identity is that their method names on their own are common names of much more generic functions in other languages (i.e. IterTools.interleave) / JS libraries (i.e. lodash.identity), and are names we may consider in the future for an IterTools JS proposal, or something else.

Also to mention, I've seen a number of compilers in different languages use the term "cooked" to distinguish it from "raw". In Rome we use it like this:

jsTemplateElement.create({
  cooked: "",
  raw: "",
})

"cooked" its not exactly common nomenclature in JS. I'd suggest String.interpolate or String.interp. Having String.interpolate doesn't preclude other kinds of interpolate functions/methods from other sources with a different meaning. I'm not sure how often I see interpolate as a standard function (I've generally seen either lerp for linear interpolation or tween for animation frame interpolation/easing). Also, the fact it is namespaced on String makes it fairly obvious its intended use.

FWIW, MDN refers to "cooked" strings within their template literal documentation. Excerpt:

However, illegal escape sequences must still be represented in the “cooked” representation. They will show up as undefined element in the “cooked” array:

function latex(str) {
  return { "cooked": str[0], "raw": str.raw[0] }
}

latex`\unicode`

// { cooked: undefined, raw: "\\unicode" }

Could it be String.parsed? Just like JS engine parses template literals. For me 'cooked' feels like a synonym for 'parsed'.

@GreLI that's an interesting angle.

It might be a bit of a squatting hazard given JS does already have Number.parseFloat - which parses a regular number token (afaik; not 100% sure it's free of quirks) and analogous companions (Boolean.parse, String.parse) don't strike me as too far fetched to consider leaving space for. Tags can only address raw/cooked string values rather than string tokens - the former are products of parsing, the latter is input to parsing (w/ the quotation marks, etc).

OTOH, "parsed" is not "parse", and I can see how that could make the difference.

Speaking of that distinction: I think parse v parsed is a great example of why nouny/adjectival naming for tags may be preferable over verb names in general - it seems particularly clear when contrasting these that the first would be "off". Raw is adjectival, too, and while a precedent of one may not count for much, (anecdotally) it seems like the convention of tag names communicating something the string is rather than what's being done with it is pretty widespread (e.g. "html", not "createTemplate"). So (for example) I'd suggest "interpolated" is better than the previously discussed "interpolate".

At first glance, the past-tense parsed doesn't feel much like JavaScript's existing stdlib, I'm not sure if anything is named that way, but a quick look at MDN for global object methods the only one I was able to find was Promise.allSettled

In a more general sense, "parsing" to me implies syntactic analysis of a string or the transformation between data types, neither of which feel terribly relevant here.

Looking around for alternatives I found that Golang's grammar uses "raw" vs "interpreted". I have similar reservations as I do parse, but I think methods named interpret are few and far in between so maybe that's fine.

I wanted to use this function in a template tag the other day in the way suggested in the readme:

function myTag(strings, ...exprs) {
  let transformedStrings = strings.map(someTransformation);
  
  return String.cooked(transformedStrings, ...exprs);
}

This made me like cooked less. By the time I've prepared the data (in this example), it's no longer a template-strings array: it's just an arbitrary array of strings.

That is, I've already processed the strings at the point at which I want to call this function. So any name which suggests that it is processing the strings themselves, rather than just mashing them together, is a bad name. (For example, parsed has exactly the same problem as cooked.)

So my vote is now for interpolate or similar.

(This usage also makes it clear, I think, that identity is a bad name. identity only makes sense when it's used as a template tag, not when used for building other template tags.)

I could also see a case for splitting out the two use cases: have a String.interpolate(array1, array2), for use in building template tags, and a String.identity(array1, ...exprs) for use as a default template tag.

How about pasteurized?

I like String.interpolate the most.

I think cooked is good, better not to worry about it and be happy with a carefully considered name even if there are other options. It's a feature, not a bug, that it uses a different term than golang even though I like golang and think their name is also fine. Being a contrast against raw, it is a solid choice.

I think I might have mentioned this in a TC39 plenary meeting at one point, but I couldn't find it in the notes with a quick look. In general I think using puns to name things can be confusing for developers (numbering likely in the millions or tens of millions worldwide) who aren't fluent in English.

I suppose with general purpose translation tools "interpolated" would do better but with docs in an editor or a search it would be quick to find the meaning.

As for raw vs cooked, there are a lot more definitions for raw than uncooked. So it's not necessarily raw as in food, though I'm sure a lot think of that. I have thought of it as raw as in material, like raw wood. The word to describe prepared wood isn't "cooked". Even for food it breaks down w/ pasteurized as I mentioned.

I might have changed my choice to interpolate. 🤔

Tag names should be descriptive/declarative, not verbs. I’m not married to a particular name, but I think that factor is important. Old meeting notes suggest this reasoning was used for raw itself, and in the years since, the ecosystem has generally stayed true to this convention too — tags get named things like html, not parseHTML, etc.

A name like interpolated would meet that criteria, but the “imperative” interpolate would not. In any case, I believe the latter should be reserved for a non-tag utility method, which has its own reasons to exist.

It's only technically a tag name, though. It doesn't need to be a particularly good example of what to call a userspace tag name IMO.

I do agree that they aren't imperative verbs like a function. I think the past participle would work. So I suppose String.interpolated would objectively be better.

Maybe that can be considered descriptive and declarative even though it's just changing the tense.