De‐bloating Javascript
De‐bloating Javascript / 给 JavaScript 瘦身
No really… The syntax seems to have been invented by someone who wanted to bet that he could push more brackets in a code than C++ and Lisp together. 说真的……这种语法看起来就像是某人为了打赌,想看看能不能在代码里塞进比 C++ 和 Lisp 加起来还要多的括号而发明的。
newNames.forEach((name, i) => {
allAgentContents[name] = contents[i];
agentModes[name] = modes[i];
if (compiled[i]) agentCompiledCache[name] = compiled[i];
agentViewingCompiled[name] = viewing[i];
});
Who could come up with a syntax as bloated as this? You open a parenthesis, and within the parentheses you open a curly bracket, and you have to close all of them in the right order. 谁能想出如此臃肿的语法?你打开一个圆括号,在圆括号里又打开一个花括号,然后你必须按正确的顺序把它们全部关闭。
There are cases when you have at least five or six closing parentheses thrown into the dough with closing curly brackets and a few square brackets, until the whole thing becomes indigestible. 有些情况下,你得把至少五六个右圆括号,混杂着右花括号和几个方括号一起塞进代码里,直到整个东西变得让人无法消化。
But the worst part is that the language itself is pretty lacking when you need string or calculus functions. You then download a ton of libraries to do stuff that is usually part of any basic programming language. 但最糟糕的是,当你需要字符串或微积分函数时,这门语言本身非常匮乏。你不得不下载大量的库来完成那些通常属于任何基础编程语言的功能。
Ok. I agree, it is not as bad as C or C++, where you need includes to do anything. However, the problem in the case of JS is that most of the time, you have no idea who implemented the library in the first place and who is supposed to maintain the bloody thing. 好吧,我承认,它还没像 C 或 C++ 那样糟糕——在那些语言里,你做任何事都需要包含头文件。然而,JS 的问题在于,大多数时候你根本不知道是谁最初实现了这个库,也不知道到底是谁在维护这该死的东西。
Sometimes, a page will load half of the internet to display hello in a small window. And the internet depends on that language. You can complain all you want, you can hide it in TypeScript, but the thing is still there, like a giant that guards a bridge you need to cross. 有时,一个页面为了在一个小窗口里显示“hello”,竟然要加载半个互联网的内容。而整个互联网却依赖于这门语言。你可以尽情抱怨,也可以用 TypeScript 将其隐藏,但它依然存在,就像一个守卫着你必经之桥的巨人。
A dumb, very large giant that you have to pay your respects to every time you open a page in your browser. 一个愚蠢且庞大的巨人,每次你在浏览器中打开页面时,都不得不向它致敬。
There was a time when people dreamt of the browser as the ultimate OS. The one that would rule them all. The one that would make Windows or Mac OS redundant at last. It was a beautiful dream, a wonderful rêverie where your life would blossom in the colorful pages of your browser. And they chose Javascript to embody this dream. 曾几何时,人们梦想着浏览器能成为终极操作系统。一个能统治一切的系统,一个最终让 Windows 或 Mac OS 变得多余的系统。那是一个美丽的梦想,一场美妙的幻梦,你的生活将在浏览器多彩的页面中绽放。而他们选择了 JavaScript 来承载这个梦想。
Web Assembly
But now, we have Web Assembly, which is akin to a virtual machine with its own machine code. This opens new frontiers to a different sort of coding, right? Some people have tried, and many have fought against the machine. 但现在,我们有了 Web Assembly,它类似于一种拥有自己机器码的虚拟机。这为不同类型的编程开启了新的前沿,对吧?有些人尝试过,也有许多人曾与这台“机器”抗争。
Pyodide is an impressive feat of engineering that runs Python in the browser, but it illustrates the cost of fighting JavaScript on its own terrain: you end up with two asynchronous worlds talking to each other, Python’s asyncio on one side, the JS event loop on the other, and a fragile bridge in between where every await has to remember which universe it lives in.
Pyodide 是一项令人印象深刻的工程成就,它能在浏览器中运行 Python,但这同时也说明了在 JavaScript 的地盘上与它抗争的代价:你最终会得到两个相互通信的异步世界——一边是 Python 的 asyncio,另一边是 JS 的事件循环,中间架着一座脆弱的桥梁,每一个 await 都必须记住它生活在哪个宇宙中。
Resources in the browser are scarce, as was the case when computer science started back in the fifties. I started on a computer in 1981 that had exactly 15772 bytes left to program. It creates a specific mindset, where every instruction, every structure must be investigated to the bit. 浏览器中的资源是稀缺的,就像五十年代计算机科学刚起步时那样。我 1981 年开始接触计算机时,只有 15772 字节的剩余空间可供编程。这造就了一种特定的思维方式:每一条指令、每一个结构都必须精确到比特位去考量。
To be honest, the browser is not as limited in terms of memory as my first computer, but still, the way Web Assembly works creates an environment where careful implementation is required. You don’t own the memory as in a regular program. You need to ask permission first, in a very constrained way. And furthermore, you don’t fight Javascript, you bargain with it. 老实说,浏览器在内存方面不像我第一台电脑那样受限,但 Web Assembly 的工作方式依然创造了一个需要谨慎实现的环境。你不像在普通程序中那样拥有内存,你需要以一种非常受限的方式先请求许可。此外,你不是在与 JavaScript 抗争,而是在与它讨价还价。
LispE
She is rich. Rich, powerful… LispE offers more than 450 functions in one single binary. A WASM binary that is very light. Lighter than the picture of your cat in an Instagram feed: 3.3 MB. 它很丰富。丰富且强大……LispE 在一个单一的二进制文件中提供了超过 450 个函数。这是一个非常轻量的 WASM 二进制文件。比你在 Instagram 上发的一张猫咪照片还要轻:仅 3.3 MB。
It offers functions to handle strings, calculus, matrices, regular expressions, all packed in one single place, ripe for the picking. And the API gives you a control you wouldn’t expect for such a tiny interpreter. You can return strings, Float64Array, integers, floats, arrays of strings. 它提供了处理字符串、微积分、矩阵、正则表达式的函数,所有这些都打包在一个地方,随时可供调用。而且,对于这样一个微小的解释器来说,其 API 提供的控制能力超乎你的想象。你可以返回字符串、Float64Array、整数、浮点数以及字符串数组。
And LispE is a Lisp: the AST is alive… It’s alive. If you don’t like the syntax, we propose transpilation grammars for languages indistinguishable from Python or Basic, or any other style you would dream of. Modify the grammar and you create your own language. In Greek, if you want. We already have. 而且 LispE 是一门 Lisp:它的抽象语法树(AST)是活的……它是活的。如果你不喜欢这种语法,我们提供了转译语法,可以实现与 Python、Basic 或任何你梦寐以求的风格无法区分的语言。修改语法,你就能创造属于你自己的语言。如果你愿意,甚至可以用希腊语。我们已经做到了。
LispE doesn’t fight the Giant. It parlays with him, exchanges greetings, taps into its treasure trove of functions and DOM capabilities. You become his best friend, and he invites you to his table as a guest, not as the main meal. LispE 不与巨人抗争。它与巨人谈判、互致问候,并利用其函数宝库和 DOM 能力。你成了他最好的朋友,他邀请你作为客人坐在他的餐桌旁,而不是作为他的盘中餐。
Pay the toll / 支付过路费
If you want to pay the toll to the Giant, LispE offers evaljs and asyncjs to execute some Javascript code from within LispE:
如果你想向巨人支付过路费,LispE 提供了 evaljs 和 asyncjs,以便在 LispE 内部执行一些 JavaScript 代码:
(setq a (evaljs "10 + 20 + 30")) ; execute some JS code
; call_llm is a user-defined JS function in the page
(asyncjs `call_llm("Implement a piece of code in Python to sort strings");` 'mycallback)
(defun mycallback(theresult) ...)
asyncjs is a Promise to the Giant to come back once his task is over.
asyncjs 是对巨人的一个承诺,即一旦任务完成,就会回来。
De-bloat your world / 给你的世界瘦身
On the other side of the bridge, a man is seated on a bench, his face ashen. “I knew,” he says. “I said it in 1995. I, Wirth, said that faster computers and larger models would not solve our problems. We need to keep our code lean.” 在桥的另一边,一个男人坐在长椅上,脸色苍白。“我早就知道,”他说,“我在 1995 年就说过。我,沃斯(Wirth),说过更快的计算机和更大的模型解决不了我们的问题。我们需要保持代码精简。”
He looks at you, then at the small binary that has just crossed the bridge. Small as a hobbit, swift as the Mearas. “Look what LispE proposes: 450 functions exposed in the browser, in a single auditable binary.” 他看着你,又看了看刚刚过桥的那个小小的二进制文件。像霍比特人一样小巧,像米亚拉斯马(Mearas)一样迅捷。“看看 LispE 提供了什么:在浏览器中暴露了 450 个函数,且集成在一个可审计的单一二进制文件中。”
For each of these functions, you would otherwise need to load libraries such as mathjs for numerical computation, lodash for collections, voca for string manipulation, simple-statistics for statistical distributions, and so on. Hundreds of megabytes of code, each with its own author, its own bugs, its own maintenance schedule.
对于这些函数中的每一个,你原本都需要加载像用于数值计算的 mathjs、用于集合操作的 lodash、用于字符串处理的 voca、用于统计分布的 simple-statistics 等等库。那可是数百兆字节的代码,每一个都有自己的作者、自己的 Bug 和自己的维护周期。
With LispE, you have one single maintained code that provides all this for free. Because LispE is an Open Source project, and its code is fully auditable. No surprises, no Garbage Collector to bring your code to its knees at the worst moment. It communicates with JS in a transparent way, through a simple API call that can return 有了 LispE,你只需维护一份代码,就能免费获得所有这些功能。因为 LispE 是一个开源项目,其代码完全可审计。没有意外,没有会在最糟糕时刻让你的代码瘫痪的垃圾回收器。它通过简单的 API 调用以透明的方式与 JS 通信,该调用可以返回……