The JavaScript Pun: tagged template literal
The JavaScript Pun: tagged template literal
JavaScript 的双关语:带标签的模板字面量
Shakespeare’s chock-full of puns, no doubt as a sign of his mastery and love of words. Rarely can you swap two words to form a correct grammatically sentence, yet he played with words like a magician. Better a witty fool than a foolish wit. Twelfth Night. In the example above, the noun “fool” flips to the adjective “foolish”, while the adjective “witty” flips to the noun “wit”. The simplest puns leverage the rules of grammar to change the meaning of words.
莎士比亚的作品中充满了双关语,这无疑是他对文字的掌控力和热爱的体现。很少有人能通过交换两个词的位置就构成一个语法正确的句子,但他却像魔术师一样玩弄文字。例如《第十二夜》中的“Better a witty fool than a foolish wit”(宁做聪明的傻瓜,不做傻气的聪明人)。在上面的例子中,名词“fool”(傻瓜)变成了形容词“foolish”(傻气的),而形容词“witty”(聪明的)则变成了名词“wit”(聪明人)。最简单的双关语利用语法规则来改变词义。
Then there are puns that play with phrases in a way that leverages context outside the grammar to change the meaning. Here’s one of my favorites: Put out the light, and then put out the light. Othello. The first phrase literally means to extinguish a candle, but the second is a metaphor for killing someone (in this case, Desdemona).
还有一些双关语通过利用语法之外的语境来改变短语的含义。这是我最喜欢的一个例子:《奥赛罗》中的“Put out the light, and then put out the light”(熄灭灯火,然后熄灭生命之光)。第一个短语字面意思是熄灭蜡烛,但第二个短语则是杀人的隐喻(在这里指代苔丝狄蒙娜)。
The formal dictionary definition of a pun usually talks about the “humorous” effect. pun /pʌn/ noun: The use of a word in such a way as to suggest two or more meanings or different associations, or of two or more words of the same or nearly the same sound with different meanings, so as to produce a humorous effect; a play on words. Oxford English Dictionary. Now, I very well believe humor is in the eye of the human. What’s funny to me isn’t always funny to you. But I’d like to introduce you to the greatest pun I’ve ever discovered. It isn’t in English.
字典对双关语的正式定义通常会提到“幽默”效果。双关语(pun)名词:指通过某种方式使用一个词,使其暗示两种或多种含义或不同的联想;或者使用两个或多个发音相同或相近但含义不同的词,从而产生幽默效果;即文字游戏。(《牛津英语词典》)。当然,我相信幽默感因人而异。我觉得好笑的,你不一定觉得好笑。但我还是想向你介绍我发现的最伟大的双关语。它不是英语。
Natural languages and programming languages have one property in common: grammar. You’ve already seen what a pun can do with that. Tagged Template Literal. First, a quick background on the grammar. In JavaScript, there’s a thing called a tagged template literal that lets you do powerful string manipulation like this:
自然语言和编程语言有一个共同点:语法。你已经见识过双关语是如何利用这一点的了。带标签的模板字面量(Tagged Template Literal)。首先,简单介绍一下语法背景。在 JavaScript 中,有一种叫做“带标签的模板字面量”的东西,它允许你进行强大的字符串操作,如下所示:
const systemPrompt = dedent`
You are a code review agent.
Follow these steps:
1. Before reviewing the PR, find recent related PRs.
2. ...
3. ...
4. ...
`;
In this code, dedent is the tag function, which processes the template literal to remove excessive indentation. A tag function receives the literal’s text pieces and the evaluated ${...} values as separate arguments, so it can do whatever it likes with each.
在这段代码中,dedent 是标签函数,它处理模板字面量以去除多余的缩进。标签函数会将字面量的文本片段和求值后的 ${...} 值作为单独的参数接收,因此它可以对每一部分进行任意处理。
Templating Languages. Most templating languages let you write the template in the same medium as the end product: text with holes where the variables go. Any time your controls live in the same system they are controlling, things get interesting. There is some Gödel incompleteness side-quest worth exploring here. But I digress. Here’s a quick example of a template: hi {{ name }}. The {{ }} syntax is very common. In fact, the following templating languages use it: Mustache, Handlebars, Jinja2, Django templates, Liquid, Angular templates, Vue templates.
模板语言。大多数模板语言允许你以最终产品的相同媒介编写模板:带有变量占位符的文本。每当你的控制逻辑与它所控制的系统处于同一系统时,事情就会变得有趣。这里有一个值得探索的哥德尔不完备性相关的旁支话题。但我跑题了。这是一个简单的模板示例:hi {{ name }}。{{ }} 语法非常常见。事实上,以下模板语言都使用它:Mustache、Handlebars、Jinja2、Django 模板、Liquid、Angular 模板、Vue 模板。
Prompt Template Literal. Check this out. We can define a tag function called prompt that looks like it’s accepting {{ }} templates.
提示词模板字面量。看看这个。我们可以定义一个名为 prompt 的标签函数,它看起来就像是在接收 {{ }} 模板一样。
const userPrompt = prompt`
Please review my code.
- Link to PR: ${{ url }}
- Extra notes: ${{ notes }}
- Timestamp: ${{ time }}
`;
It looks familiar and easy on the eyes, right? Behind the scenes, it’s producing a string that will be processed by an observability tool (Helicone) to help analyze the prompts.
看起来很熟悉且赏心悦目,对吧?在幕后,它生成了一个字符串,该字符串将由可观测性工具(Helicone)处理,以帮助分析提示词。
In my opinion, the cool part is that the apparent {{ }} template syntax emerges in our JavaScript code by coincidence: ${...} evaluates whatever is inside it, and JavaScript’s { name } object shorthand is equivalent to { name: name }. The tag function, prompt, now has all it needs to annotate the string properly. JavaScript sees one thing, and you see another. The {{ url }} syntax lives in your head. … crickets …
在我看来,最酷的部分在于,这种显而易见的 {{ }} 模板语法是在我们的 JavaScript 代码中巧合产生的:${...} 会对其内部的任何内容进行求值,而 JavaScript 的 { name } 对象简写等同于 { name: name }。现在,标签函数 prompt 拥有了正确标注字符串所需的一切。JavaScript 看到的是一种东西,而你看到的是另一种。{{ url }} 语法只存在于你的脑海中。……(一片寂静)……
Alright, maybe I overplayed the pun, but I’m absolutely proud of it. I worked with Justin from Helicone on this back in 2024. It was an idea I’d been using internally, which Justin then made official in the SDK. I thought the pun was funny. Justin was happy to include it. A pun is one string with two parses. In Grammar models are back, baby! I take that seriously and hand back a probability distribution over them. In Spatial languages I make it worse and hand the parser a second dimension.
好吧,也许我有点过度解读这个双关语了,但我确实为此感到自豪。我曾在 2024 年与 Helicone 的 Justin 合作过这个项目。这是一个我一直在内部使用的想法,后来 Justin 将其正式加入到了 SDK 中。我觉得这个双关语很有趣,Justin 也乐于将其包含进去。双关语就是一个字符串有两种解析方式。在“语法模型回归”中,我认真对待这一点,并返回它们的概率分布。在“空间语言”中,我变本加厉,给了解析器第二个维度。