正确设计编程语言(2024)

Lobsters Hottest 新闻

摘要

这篇博客文章提出了新编程语言的设计指南,强调了修复常见问题,如缩进多行字符串、正确的文件路径处理、一致的文件扩展名和可扩展的语法特性。

<p><a href="https://lobste.rs/s/fdgccx/design_your_programming_languages_right">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/09/22 06:34

# 设计你的编程语言! 来源:https://blog.veritates.love/design-it-right 我认为我们应该为新的编程语言及其配置设定一些基本准则。你懂的? 这只是我对一些特性的随想——我认为你应该包含这些特性,至少应该考虑它们,而不是*过早地*排除它们。还有一些我目前尚未有明确答案的其他话题。 ## 已解决的问题 / 无关紧要的议题 ### 缩进多行字符串! 当你在代码中嵌入多行字符串,却发现不得不闭上眼睛假装当前的缩进层级不存在,因为原始内容直接侵占了左侧的空白时,这真的很丑陋。 这是一个已解决的问题。Dhall (https://github.com/dhall-lang/dhall-lang/blob/master/standard/multiline.md) 做得相当好(虽然我不太喜欢那里的转义规则),而 Nix/Lix (https://docs.lix.systems/manual/lix/stable/language/values.html#type-string) 也有类似的规则。 我在 Ve. dedent (https://blog.veritates.love/assets/js/verity.js) 中为 JavaScript 的模板字面量实现了类似的逻辑,我对此非常满意。我也尽力为 PureScript(还有 Python?)尝试了,但缺少源代码与转义/插值文本之间的区分使得实现更加困难,更像是一个适用于某些情况的工具,而不是一个若能内置其中本可成为的系统化方案。 缩进多行字符串只是你可以投入额外几小时在早期解决的问题,避免其成为用户的问题,然后又因向后兼容性问题而无法更改。 ### 相对文件路径 文件路径应相对于它们所在的文件,或相对于一个定义明确的项目根目录。这主要适用于配置,较少适用于运行程序(对于程序,工作目录通常足够),但……导入应该是可预测的。 值得注意的是,Docker Compose (https://docs.docker.com/compose/how-tos/multiple-compose-files/extends/#understanding-multiple-compose-files) 和 Rust 的 Cargo (https://doc.rust-lang.org/cargo/reference/config.html#config-relative-paths) 的配置文件在这点上都做错了。 同样,你必须在一开始就把事情做对,或者制定可靠的版本控制计划。(当然,那些没有花心思在一开始就把事情做对的编程语言,通常也没有足够好的版本控制策略来处理这个问题。) ### 文件扩展名 选择一两个扩展名,然后坚持使用它!记住,如果你是一种新语言,你是凭现有生态系统的善意而加入的访客,应该遵守它们的规则。 IDE 和在线代码查看器/Git 代码托管平台中的语法高亮主要基于文件扩展名。如果你没有一个可识别的文件扩展名,你的用户将不得不付出更多努力。 举个例子,Bazel 在名为 `WORKSPACE`、`BUILD` 和 `.bzl` 或 `.bazel` 的文件中使用 Starlark。Starlark 恰好有 Python 的语法高亮,这很好,你可以利用这一点。 但是,如果扩展名各不相同甚至有些文件没有扩展名,就很难让你的 IDE 为它们提供高亮。(如果这些名称是可配置的就更难了,但我不认为 `WORKSPACE` 和 `BUILD` 是可配置的吧?)如果必须包含所有可能出现的文件形式,用 `grep` 搜索文件也会更难。等等。 ### 逗号 另一个已解决的问题:允许尾部逗号!(如果喜欢的话,可能也允许头部逗号……或者使用真正的项目符号。) ### 可扩展语法 很多语言在数字字面量上犯过错误(想添加更多前缀或后缀,但路径被向后兼容性阻塞),或字符串/正则表达式转义(请使用像 `"\u{XXXX}"` 这样的分隔转义!),或关键字上犯过错。 这更多是我个人的观点,但我讨厌裸关键字。我认为关键字应该带有标记(sigil)以清晰地表示它们是关键字,并允许在不破坏将其用作标识符的旧代码的情况下扩展语言以包含更多关键字。你*真的*认为你能一次就得到完美的一组关键字吗?……你能指出一个做到了的编程语言吗? ## (大多)未解决、复杂的问题 ### 开发者体验 vs. 已发布的代码 在开发过程中迭代代码,与拥有一个干净、原始的发布版本……这是相当不同的事情,我认为这些工作流程应该得到尊重! 例如,在开发时,我们经常将 Web 服务器放在不同的端口和/或局域网主机上,并使用 HTTP 或自签名 HTTPS(甚至在少数情况下使用 `file:///`!),而在生产环境中,它可能位于某个特定路由后面的反向代理之后,等等。 ### 版本控制 版本控制意味着很多东西。 我以前从未真正*解决过*的问题之一是如何处理*跨版本*的代码。 比如说,我想在我的已发布软件的不同版本之间有一个迁移脚本。好吧,我猜它的代码必须存在于更新的版本中——之前的版本不可能知道接下来会发生什么。但你如何测试它?你有点需要从源代码管理中检出你代码的前一个版本,并让两者并行运行。(这也是“开发”和“发布”模式相当分离的情况!) 总的来说,如果你期望人们用你的编程语言编写库,给他们一种合理的讨论版本的方式。这个领域比较酷的工具之一是那些检查库的 API(特别是如果它是强类型的话!)以确定它应该是补丁版本、次版本还是主版本的工具。 *然而*,我必须强调:版本号总是需要主观判断的。它们是一种不完美的沟通工具,而不是数学上精确的抽象。 --- 哦,另一个偏好:请务必在你的发布版本号中包含日期!它不必*包含在*版本号中,但应该易于获取,显示在旁边或工具提示中,或在一个规范的网页上。如果不了解所有相关软件(语言、运行时、包、依赖项)的发布日期,几乎不可能进行*跨*软件的版本比较。 ### 文件监视 这是围绕构建系统等更大讨论的一部分,但是。 我从未发现有可能在原本没有文件监视功能的构建系统上后期添加详细的文件监视功能。除非,比如,编写一个完整的 Python 程序去解析文件、重建它们的依赖关系树、确保我知道每个文件的使用方式以及它是否相关,如果配置更改则重新加载整个监视器,等等。 ### 与工具的集成 比如 `find`/`grep`:如果你能让构建工具告诉你所有需要搜索的文件,然后再决定是否包含依赖项,那就更好了。(另外,这种文件/通配符列表也为你迈向文件监视提供了第一步,虽然(同样)你真正需要的是适当的集成来处理新增的文件、更改的配置等等!) 如果你想添加适当的代码搜索,能够区分搜索词是出现在标识符中还是字符串中,或是在类型中还是术语中,等等,那就更好了。是的。^_^

相似文章

编程语言中的一些好点子

Hacker News Top

本文讨论了三种编程语言特性:用于在Crystal和TypeScript等静态语言中实现动态感觉的流类型、用于确保Rust内存安全的借用检查,以及用于D语言中不变性检查的契约编程。

七大编程原语言(2022)

Hacker News Top

一篇文章探讨了七种构成大多数现代编程语言基础的编程语言原型(原语言),认为学习植根于这些原型的基础知识比选择特定语言更重要。

Stroustrup法则(2024)

Hacker News Top

Bjarne Stroustrup的法则指出:对于新特性,程序员更偏好显式语法,但一旦该特性被确立,他们就更倾向于简洁表示法。本文探讨了 Rust 和 Python 中的示例,并讨论了这对语言设计和教学的影响。

Syntax with Purpose in a Programming Language

Lobsters Hottest

这篇文章探讨了编程语言语法设计的重要性,认为语法应准确反映语言的计算模型和心智模型,而非为了熟悉感或简洁性随意拼凑。作者通过分析OCaml、Lisp/Clojure和JavaScript的语法设计,并介绍自己设计的语言Saul,强调了统一性和语义一致性。