Design your programming languages right (2024)
Design your programming languages right (2024)
妥善设计你的编程语言(2024)
I just think we should have some ground rules for new programming languages and their configuration. Yʼknow? Just some rambly thoughts on features I think you should include, or at least think about and not block yourself out of including. And other topics I am thinking about with no real answers yet. 我认为我们应该为新的编程语言及其配置制定一些基本规则。你懂的?这只是一些关于我建议你包含(或者至少应该考虑,以免日后无法添加)的功能的随笔。此外还有一些我正在思考但尚未找到明确答案的话题。
Solved problems / non-issues
已解决的问题 / 非问题
Indented multiline strings! Itʼs so ugly when you go to embed a multiline string into your code, and you realize that you’re going to have to close your eyes and pretend the current indentation level does not exist, as the raw contents take over the left gutter. This is a solved problem. Dhall did a pretty good job of it (although I am not too fond of the escaping rules there), and Nix/Lix have similar rules. I implemented similar logic for JavaScript template literals in Ve.dedent, I am very happy with it. And Iʼve tried my best for PureScript (and Python?), but not having the distinction between source and escaped/interpolated texts makes it much harder, and more of a tool that works for some cases than a systematic approach that it could be if it was baked in. Indented multiline strings are just a thing that you can put a few extra hours of effort into fixing early, before it becomes a problem for your users and then you canʼt change without backwards compatibility issues. 缩进的多行字符串! 当你在代码中嵌入多行字符串时,如果发现必须“闭上眼睛”假装当前的缩进级别不存在,任由原始内容占据左侧边栏,那看起来真的很丑。这是一个已经解决的问题。Dhall 在这方面做得很好(尽管我不太喜欢那里的转义规则),Nix/Lix 也有类似的规则。我在 Ve.dedent 中为 JavaScript 模板字面量实现了类似的逻辑,对此我非常满意。我也曾尝试为 PureScript(以及 Python?)实现类似功能,但由于缺乏对源代码与转义/插值文本的区分,这变得困难得多,它更像是一个仅在某些情况下有效的工具,而不是一种如果内置其中本可以实现的系统化方案。缩进多行字符串是一个值得你尽早投入几小时去解决的问题,否则等它成为用户的问题时,你将因向后兼容性问题而无法再进行修改。
Relative file paths File paths should be relative to the file theyʼre in, or to a well defined project root. This mostly applies to configuration, less so running programs (for which a working directory is usually fine), but like … imports should be predictable. Notably, configuration files for both Docker Compose and Rustʼs Cargo get this wrong. Again, you have to get it right up-front, or figure out solid plans for versioning. (But of course, programming languages that donʼt have the thought put in to get it right up front, usually donʼt have good enough versioning policies to deal with this either.) 相对文件路径 文件路径应该相对于它们所在的文件,或者相对于定义明确的项目根目录。这主要适用于配置,对于运行中的程序(通常使用工作目录即可)则次之,但……导入路径应该是可预测的。值得注意的是,Docker Compose 和 Rust 的 Cargo 的配置文件在这点上都做错了。同样,你必须在初期就将其设计正确,或者制定稳健的版本控制计划。(当然,那些在初期没有深思熟虑的编程语言,通常也没有足够好的版本控制策略来处理这个问题。)
File extensions Pick an extension or two, and stick to it! Remember that if youʼre a new language, youʼre a guest entering existing ecosystems by their good grace and should work on their terms. Syntax highlighting, in IDEs and online code viewers/git forges, is mainly based on the file extension. And if you donʼt have a recognizable file extension, your users are going to have to work harder. As one example, Bazel uses Starlark in files named WORKSPACE and BUILD and .bzl or .bazel. Starlark just has Python syntax highlighting, which is nice that you can use that. But itʼs hard to convince your IDE to highlight them if thereʼs different extensions and extensionless file names. (Itʼs even harder if these names are configurable, but I donʼt think WORKSPACE and BUILD are?) Itʼs harder to grep through the files if you have to include all the forms that it can occur. And so on. 文件扩展名 选定一两个扩展名,并坚持使用它!请记住,如果你是一门新语言,你就是进入现有生态系统的“客人”,必须遵循它们的规则。IDE、在线代码查看器和 Git 托管平台中的语法高亮主要基于文件扩展名。如果你没有可识别的文件扩展名,你的用户将不得不付出更多努力。举个例子,Bazel 在名为 WORKSPACE、BUILD 以及 .bzl 或 .bazel 的文件中使用 Starlark。Starlark 直接使用 Python 语法高亮,这很好。但如果存在不同的扩展名和无扩展名的文件名,就很难让 IDE 正确识别并高亮它们。(如果这些名称是可配置的,那就更难了,不过我不认为 WORKSPACE 和 BUILD 是可配置的?)如果你必须包含所有可能出现的形式,那么通过 grep 搜索文件也会变得更困难。诸如此类。
Commas Another solved problem: allow trailing commas! (And possibly leading commas, if you feel like that … or actual bullet points.) 逗号 另一个已解决的问题:允许尾随逗号!(如果愿意的话,甚至可以允许前导逗号……或者实际的项目符号。)
Extensible syntax A lot of languages have made mistakes around numeric literals (wanting to add more prefixes or suffixes, but the path forward is blocked by backwards compatibility), or string/regex escapes (use delimited escapes like “\u{XXXX}”!), or keywords. Itʼs more my personal opinion, but I dislike bare keywords. I think keywords should come with a sigil to clearly denote them as a keyword and allow extending the language with more keywords without breaking old code that used them as identifiers. Do you really think youʼll get the perfect set of keywords right the first time? … can you point to a programming language that did? 可扩展的语法 许多语言在数字字面量(想要添加更多前缀或后缀,但被向后兼容性阻碍)、字符串/正则表达式转义(应使用如 “\u{XXXX}” 这样的定界转义!)或关键字方面犯过错误。这更多是我的个人观点,但我讨厌裸露的关键字。我认为关键字应该带有符号(sigil),以明确将其标记为关键字,并允许在不破坏将这些词用作标识符的旧代码的情况下扩展更多关键字。你真的认为你能一次性设计出完美的关键字集合吗?……你能指出一门做到了这一点的编程语言吗?
(Mostly) unsolved, nuanced problems
(基本)未解决的、微妙的问题
Developer experience vs Released code iterating on code as youʼre developing it, versus having a nice clean, pristine released version … theyʼre quite different things, and I think these workflows should be respected! e.g. when developing, we often put web servers on different ports and/or LAN hosts, and use HTTP or self-signed HTTPS (or even file:/// in the few cases we can get away with it!), whereas in production it might be behind a reverse proxy under some specific route, and so on. 开发体验与发布代码 在开发过程中迭代代码,与拥有一个干净、原始的发布版本……这是两码事,我认为这些工作流都应该得到尊重!例如,在开发时,我们经常将 Web 服务器放在不同的端口和/或局域网主机上,并使用 HTTP 或自签名 HTTPS(甚至在少数情况下使用 file:///),而在生产环境中,它可能位于反向代理之后,处于特定的路由下,等等。
Versioning Versioning means a lot of things. One of the problems that I havenʼt really seen solved before, is how to deal with code across versions. Like, letʼs say that I want to have a migration script between versions of my released software. Well, I guess the code for it has to live in the later version – itʼs not like the previous version knew what was coming up. But how do you test it? You kind of need to check out the previous version of your code from source control, and have them both in parallel. (This is also something where the “development” and “release” modes are pretty separate!) And in general, if youʼre expecting people to write libraries in your programming language, give them a sensible way to talk about versions. One of the cooler tools in this area are the ones that check a libraryʼs API (especially if it is typed!) to determine whether it should be a patch/minor/major release. However, I must stress: version numbers are always going to be subject to judgment calls. They are an imperfect tool of communication, not a mathematically precise abstraction. Oh another hobby horse: Please always include dates with your release version numbers! It doesnʼt have to be in the version number, but it should be easily accessible, displayed beside it or in a tooltip or on a canonical webpage. Itʼs nearly impossible to compare versions across software (languages, runtimes, packages, dependencies) without having a sense of release dates of it all. 版本控制 版本控制意味着很多事情。我尚未真正看到有人解决的一个问题是:如何处理跨版本的代码。比如,假设我想为已发布的软件版本之间编写一个迁移脚本。好吧,我想这个脚本的代码必须存在于较新的版本中——毕竟旧版本不可能预知未来。但你该如何测试它呢?你几乎需要从版本控制中检出旧版本的代码,并让两者并行存在。(这也是“开发”模式和“发布”模式截然不同的地方!)总的来说,如果你期望人们用你的编程语言编写库,请给他们一种合理的版本表达方式。该领域较酷的工具之一是那些检查库 API(特别是如果它是强类型的!)以确定它应该是补丁/次要/主要版本的工具。然而,我必须强调:版本号始终取决于人为判断。它们是一种不完美的沟通工具,而不是数学上精确的抽象。哦,还有个个人偏好:请务必在发布版本号中包含日期!它不必包含在版本号字符串中,但应该易于获取,显示在版本号旁边、工具提示中或官方网页上。如果没有发布日期,几乎不可能比较不同软件(语言、运行时、包、依赖项)之间的版本。
File watching This is part of a larger discussion around build systems and the like, but. Iʼve never found it possible to retrofit detailed file watching onto build systems that didnʼt have it. Without, like, writing a whole Python program to go and parse files, reconstruct their dependency tree, make sure I know how each file is getting used and if it is relevant at all, reload the whole watcher. 文件监视 这是围绕构建系统等更大讨论的一部分。但我从未发现可以将详细的文件监视功能“改装”到原本不支持它的构建系统中。除非编写一个完整的 Python 程序去解析文件、重建依赖树、确保我知道每个文件是如何被使用的以及它是否相关,否则就只能重载整个监视器。