Dave Lucia's Blog

发布于 2025 年 5 月 12 日

为 Elixir 引入 Lua

Elixir 库的第一个稳定版本 Lua v0.1.0 已经发布到 hex.pm!

Lua 是一个允许你直接在 BEAM VM 上执行任意、沙盒化的 Lua 程序的库。这 不是 嵌入 C Lua 运行时和编译器,而是一个完整的 Lua 5.3 实现。这一壮举得益于底层的 Luerl library,它完全用 Erlang 实现了 Lua 解析器、编译器和运行时。

Lua Elixir 库扩展了 Luerl library 的功能,改进了错误消息,并提供了强大的文档。

功能亮点包括:

使用 Elixir APIs 扩展 Lua

Lua Elixir 库有一个 deflua 宏,可以轻松地在 Elixir 中表达 APIs,这些 APIs 可以通过 Lua.load_api/2 暴露给 Lua。

defmodule MyAPI do
 use Lua.API
   
 deflua double(v), do: 2 * v
end
import Lua, only: [sigil_LUA: 2]
  
lua = Lua.new() |> Lua.load_api(MyAPI)
{[10], _} = Lua.eval!(lua, ~LUA[return double(5)])

编译时语法评估

提供了一个 ~LUA sigil,允许在 Elixir 编译时验证 Lua 语法。

iex> import Lua, only: [sigil_LUA: 2]
#iex> {[4], _} = Lua.eval!(~LUA[return 2 +])
** (Lua.CompilerException) Failed to compile Lua!

完善的文档

查看 Lua Hex docs 获取详细的文档和示例,了解如何使用 Lua 和 Luerl。

还有一个 Livebook 可以帮助你入门。

诞生于 TV Labs

Lua Elixir 库最初是 TV Labs 的一个概念验证项目,我在那里是联合创始人兼 CTO。在 TV Labs,我们需要执行任意代码,以便我们的客户能够针对物理电视和其他流媒体设备编写高级集成测试。最初只是一个原型,后来我们深入研究了 Luerl 的细节,提高了它的可用性和错误消息,同时使其易于从 Elixir 中使用。TV Labs 使用 Lua 作为其 drag and drop Automation builder 的编译目标,用户可以在其中指定测试的高级工作流程,我们处理调度和底层执行。

Elixir Lua 库和 Luerl 使我们能够构建一个用于物理设备上基于视觉的集成测试的工作解决方案,而无需协调额外的 JavaScript 或 Python 虚拟机,并在靠近物理设备的计算上执行代码。

Luerl 是如何诞生的

Robert Virding 是一位活着的传奇人物。除了是 著名的电影明星 之外,Robert 最为人所知的是他在 80 年代中期与 Ericsson 的 Joe Armstrong 和 Mike Williams 合作创建了 Erlang Programming Language。Erlang 最初以其在电信领域的应用以及容错、并发和不可变数据等特性而闻名,但现在被认为是一种通用语言,其虚拟机 BEAM VM 为包括 Elixir 和 Gleam 在内的许多语言提供支持。由于仅仅创建 一门 编程语言没有乐趣,Robert 还创建了 Lisp flavored Erlang (LFE)、一个 Erlang 中的 Prolog 解释器,名为 Erlog,当然还有 Lua 的一个实现,名为 Luerl

Code BEAM EU 2024 期间,我很荣幸能与 Robert 一起发表演讲。由于 Luerl 对他来说似乎是一个业余项目,我问他为什么一开始还要创建它。Robert 笑了笑说:

我在 Erlang 上写了一个 Prolog,这很有趣。然后在 Erlang 中写了一个函数式 Lisp,也很有趣。但后来我意识到,在 BEAM 上实现一种命令式或面向对象的语言会很棒,所以我选择了 Lua 并开始了。这就是 Luerl 的诞生方式。

如果我从这次经历和与 Robert 的合作中学到了什么,那就是他仍然从创造和实验中获得巨大的乐趣,而 Luerl 就是其中许多例子之一。

Lua 和 Luerl 的未来

Lua 一直是我们构建 TV Labs 自动化平台的良好基础;但是,Luerl 中还有许多需要改进的地方,以使其更有用:

  1. 错误消息的质量需要大幅提高
  2. 堆栈跟踪通常缺乏有用的上下文和信息
  3. 文档和示例需要大量工作
  4. 与内存相关的沙盒功能需要更多检查和探索
  5. 与更大的 Lua 生态系统进行更深入的集成

为此,Robert 和我已经讨论过将 Elixir Lua 库合并到 Luerl 中。我们希望这样做并发布 2.0.0 版本的 Luerl,继续改进文档,删除已弃用的接口,并显着改进错误消息和堆栈跟踪。

如果您有兴趣参与其中,请加入 SlackDiscord,或者 在 Github 上提出 issue

谢谢!

发现错误/bug?在 Github 上编辑这篇文章