OTP and Gleam

Lobsters Hottest 新闻

摘要

Gleam语言创造者Louie深入解释了OTP的核心概念,以及Gleam如何通过类型安全的方式与OTP协同工作,实现了与Erlang/Elixir完全兼容的进程间通信和监督者等构建块。

<p><a href="https://lobste.rs/s/vhp5x9/otp_gleam">Comments</a></p>
查看原文
查看缓存全文

缓存时间: 2026/06/11 13:39

**TL;DR:** 演讲者 Louie(Gleam 创造者)深入解释了 OTP 是什么、Gleam 如何与 OTP 协同工作,以及如何通过类型安全的方式实现进程间通信,最终证明 Gleam 能完全发挥 OTP 的魔法,同时保留静态类型的好处。 ## 引言 大家好,非常感谢。今天真是激动人心的一天——我们有了一整天的 Gleam 演讲,整个 Gleam 轨道。这个演讲叫做“OTP 与 Gleam”,我想展示这两个重要的东西如何协同工作,并解释它们能不能协同、有哪些问题和挑战,还要深入内部看看为什么决策是那样做出的,因为这种背景能帮助你更好地理解系统。 我是 Louie,我创造了 Gleam,所以他们让我来做这个演讲。 ## 什么是 OTP? OTP 这个名称(开放电信平台)本身没什么意义,刚开始接触 BEAM 时很难准确理解它究竟是什么。我认为要最好地理解它,需要稍微后退一步,把 BEAM 看作一个整体。 BEAM 给了我们(也喜欢吹嘘的)特性:大规模可扩展性、无与伦比的可靠性、生产环境可观测性、可靠的低延迟能力以及分布式计算。但仔细想想,BEAM 并没有直接给我们这些特性——它给了我们**消息**,给了我们**错误隔离**。你可以看到这些事情之间的关系,但仅仅拥有一个原语,并不一定意味着你拥有另一个特性。 我们的工作是获取这些原语、这些有用的工具,并将它们转化为一个拥有我们作为 BEAM 开发者想要吹嘘的特性的系统。如果只是从这些小构建块开始尝试构建,很容易犯错,尤其是处理并发之类的问题。 所以,我认为这才是 OTP 的真正含义:OTP 是一堆代码,随你的 Erlang 发行版一起提供,它利用那些 BEAM 原语,实现了一堆非常有用的设计模式,为我们提供了可以在程序中使用的一系列构建块:监督者、通用服务器等等。这些实现是由杰出的人构建的,并且经过了近 30 年的彻底测试和使用,我们知道可以信赖它们。 OTP 的最后一个部分,是一套协议、一套接口。实现这些接口的东西可以插入到更大的 OTP 系统中,比如响应系统消息的特殊进程、为某种模块行为实现回调的模块等等。这就是我对 OTP 的理解。**OTP 是 BEAM 魔法的关键**——当我们喜欢吹嘘 BEAM 的特性时,实际上可能是在吹嘘 OTP。无论你写 Erlang 还是 Elixir,这都是事实。 ## 问题:Gleam 能用 OTP 吗? 有人会在论坛上说:“哦,你不能在 Gleam 中使用 OTP,因为有类型。”而类型在本质上对 actor 之类的东西是不好的?这不可能行得通。但事实上,**它完全行得通**。我们需要让人们非常清楚,这些东西可以出色地协同工作。我们不会完全按照 Erlang 和 Elixir 的方式来做,因为它是另一门语言,但它就在那里,我们可以使用相同的框架。 ## OTP 在 Gleam 中的实现方式 OTP 在 Gleam 中以两个包的形式实现,它不是语言的一部分(类似 Erlang 和 Elixir)。在 Gleam 中分离还有一个额外原因:我们还需要在 JavaScript 上运行,而 JavaScript 没有那些 BEAM 原语,无法在其上构建 OTP。 这两个包的目标: - **生产就绪且高效**:我们希望人们做出真实的东西,而不是学术项目。 - **与 Erlang OTP 完全兼容**:我们不制造独立的 Gleam OTP,它是 Gleam 进入现有 OTP 的窗口。Gleam 程序可以借助所有前辈 BEAM 开发者创造的好东西,反过来,用 Gleam 做的东西,Elixir 的朋友们也能利用。 - **提供核心构建块**:监督者、通用服务器等。 - **静态类型安全**:在涉及并发和 actor 时,类型系统魔法不应消失。 - **富有表现力和能力**:用 Erlang 能写的程序,用 Gleam 也应该能写。不是做一个严格更弱的东西,而是等价的。 - **长期可持续**:OTP 快 30 岁了,Gleam 也应当像虚拟机一样持续到永远。 ## 如何实现类型安全?两种方法 ### 方法一:重用现有 API(以监督者为例) 以静态子进程创建监督者为例,Gleam API 与 Erlang 的工作方式非常相似,只是省略了子进程规范列表,使用了管道语法。语义完全相同,我们可以用其中一个实现另一个:导入 `start_link` 函数(私有),然后放一个漂亮的包装器,将 Gleam 期望的数据结构转换为 Erlang 期望的形状。**Erlang 已经很好了,我们不必重新发明轮子**,如果可行就使用它。 ### 方法二:重新设计 API(以通用服务器为例) 有时 API 在某种程度上不适合 Gleam,不能轻易用小函数掩盖。例如 `handle_call` 回调:在 Erlang 中一个 case 表达式可以返回整数或布尔值,但 Gleam 不允许 case 分支返回不同类型的值,也没有整数和布尔值的联合类型。所以必须设计不同的 API。 我们必须像 Erlang 那样,在同样的原语之上用 Gleam 实现 Gleam OTP。核心原语有六个:`spawn`、`link`、`trap_exit`、`monitor`、`send` 和 `receive`。前四个很容易导入或加包装。 **最大的问题是 `send` 和 `receive`**:如果直接导入 Erlang 的设计,接收者和消息类型之间没有关系,任何进程可以向任何进程发送任何类型消息,这不是我们追求的类型安全。我们希望只能向接受它们的进程发送消息。 一种常见尝试是参数化 PID:带上消息类型参数(如 `PID(Int)`),但这不够灵活——同一个 PID 需要能接收不同类型的消息(如温度和是否下雨的回复),但回复类型不同,PID 无法编码这些语义。 实际上,Erlang 已经解决了这个问题。查看 `gen` 模块内部可以发现 `from` 数据结构,它将语义标识信息附加到进程收件箱中的单个消息上,用于匹配“这是对什么的回复”。我们可以采用同样的设计,忠实地转换成 Gleam,加一个类型参数(消息类型),并把 `from` 重命名为 `subject`,`reply` 重命名为 `send`,概念已经存在。这样我们就有了类型化消息发送的方式。 对于同时从多个不同 subject 接收,可以使用 `selector`,例如接收字符串消息和整数消息,然后把整数映射成字符串。 所有原理都有了,这足够实现 gen_server 吗?gen_server 做几件事:同步初始化(成功或失败并传回值给父进程)、持有并更新状态、处理系统消息(用于 observer 调试)、处理同步和异步消息(主要业务逻辑)。**我们有和 Erlang 相同的六个原语,可以直接复制 Erlang 的实现**——打开 Erlang 源码,直接翻译过来,只做必要的类型适配。 ## 结论 Gleam 能够完全使用 OTP 的魔法,同时保持静态类型安全。通过巧妙的设计(如 subject/selector),我们既获得了类型系统的好处,又没有牺牲表达能力。Gleam OTP 与 Erlang OTP 完全兼容,而且能在相同的时间尺度上持续发展。 **Source:** https://www.youtube.com/watch?v=DJwxAJoUUOU

相似文章

Gleam and the value of small

Lobsters Hottest

Gleam 是一门刻意保持简洁的函数式编程语言,通过精简关键字、避免重复来提升可读性和开发体验,其设计理念是“少即是多”。

Gleam v1.17.0

Hacker News Top

Gleam v1.17.0 引入了 `gleam export escript` 命令以创建单文件 BEAM 程序,在语言服务器中高亮引用,以及常量 `todo` 表达式。此外,首届 Gleam Gathering 大会的视频也已发布。

Core Team Panel - Gleam Gathering 2026

Lobsters Hottest

Gleam 核心团队在 2026 年聚会上分享了个人故事、2026 年计划、社区友好氛围的维持方式,以及对 AI 编码工具的看法。