哈佛大学 Lua 库设计研讨会,星期二,2 月 19 日
嵌入式编程语言 Lua [1] 的设计体现了设计师近十年来精心思考和关注的结果。然而,与 Lua 捆绑在一起的标准库并没有得到同等的关注。作为该语言的用户,我们有兴趣改进库。因此,我们将举办一个为期一天的(简短)研讨会,以提出改进库的建议。向后兼容性不是必需的;如果我们愿意,我们可以随意丢弃所有内容并重新开始!(但是,我们将坚持当前的语言定义——只有库可以随意修改。)我们很幸运地邀请到了 Lua 的主要设计师之一 RobertoIerusalimschy 与我们一起参加。
我们预计从上午 10 点到下午 4 点进行工作,并短暂休息午餐。这将是一次工作会议,而不是演讲和讨论会,我们希望能够为 Lua 团队提出非常具体、明确的建议。因此,报名人数将限制在约 20 人。
如果您想参加本次研讨会,请告知我们。请发送电子邮件至 Christian Lindig [[email protected]]。我们希望在 2 月 8 日星期五之前收到您的回复。
-- ChristianLindig?
即使您无法参加,也请提出您希望在研讨会上讨论的内容。
ReubenThomas 继续说道:在开始之前,重要的是要确定标准库的范围和目的。在我看来,标准库应该
- 只提供广泛需要的功能
- 只提供无法用 Lua 编写或在 Lua 中效率太低的功能
- 只使用标准 ANSI C 库例程(当然,除了 Lua 自己的代码之外),以完全可移植的方式
ChristianLinding? 最初列出了邮件列表中的一些最新主题,其中大多数可能不适合在研讨会上讨论;以下是列表,并附有说明
- 动态加载库以避免为每个应用程序构建 Lua 解释器。非 ANSI
- 允许查询文件和目录属性的 IO 库。非 ANSI
- 某种形式的协程或异步执行。非 ANSI;在 4.1 中已基本解决
- 标准 IP 套接字接口。非 ANSI
- 用于 UNIX 系统调用的接口(例如,exec、kill、waitpid 等)。**非 ANSI;poslib 可以做到这一点,但需要更新到 4.x 版本**
- 命名空间管理,允许库共存。**这是关于 Lua 库的观点,而不是 C 库**
- 一个缓冲区库。**C 代码已经存在于 auxlib 中;这确实应该讨论。**
**RiciLake** 插话
- 我同意 ReubenThomas 的观点,即标准库应该只提供可以用可移植的 ANSI C 编写的服务。然而,也很明显,ChristianLindig? 提出的许多增强功能对许多人来说都是有用的,并且实际上已经多次被请求。也许这里有一个折衷方案:将**标准接口**定义为一组在许多操作系统上普遍可用的设施,并可能为其中之一提供参考实现。精心设计的接口集通常是库设计中最难的部分。
- 这至少允许人们编写半可移植的代码;也就是说,代码可以移植到已实现标准接口的平台。此类接口的候选者可能包括 IP 套接字、文件属性、POSIX 的一个子集以及动态链接设施,仅举 Christian 列表中的几项。
- 强烈鼓励对标准接口进行移植,但要进行一些道德上的劝说,不要过度或不足地实现它们。精神应该是“如果你有这个功能,这就是你将其集成到 Lua 中的方式”。然后,对实现函数的简单存在性测试就足以知道该功能是否可用;如果不需要根据操作系统执行测试,那就太好了。这在一定程度上是有限制的,但不像纯 ANSI C 那样限制(事实上,它与当前的理念兼容,即数学或 io 库可能不适用于某些嵌入式平台)。
- 我第一次写这篇文章时遗漏了一件事:如果数学库能够在支持 IEEE-754 算术的平台上使用它,那就太好了。如果不支持陷阱,我不会伤心,但能够测试和设置 IEEE-754 规定的异常标志,以及至少有一种方法可以关闭陷阱(如果它们无法以其他方式支持),那就太好了。当然,还要测试 NaN 和 +-Inf。
- 返回 ReubenThomas...
以下是我的一些更高级的想法
1. 是否可以将更多 Lua 的内部机制作为库公开?
特别是,能够访问编译过程的内部机制会非常有用,例如能够将代码作为数据进行操作(而不是像现在这样诉诸字符串操作)。类似地,请参阅我过去在列表中提出的关于能够插入不同的正则表达式引擎或(更具争议性地)垃圾收集器的建议。
2. 如何用 Lua 重新实现一些标准库?
一些函数,比如 assert,可以很容易地用 Lua 实现,用 C 实现它们几乎没有优势。此外,还有一些用 Lua 编写的函数,将它们预加载到解释器中非常有用,例如 require(到 4.0)。拥有一个将 Lua 库构建到可执行文件中的框架将很容易(bin2c 已经完成了这项工作)并且有用。减少用 C 编写的代码量将提高可用性并减少维护工作。
3. 还有什么需要做的?
就标准库而言,这归结为一个很小的问题,即是否有一些缺少的 ANSI C 库位可以有效地暴露给 Lua,以及一个更大的问题,即是否有一些技术,比如模式匹配,既可以从 C 实现中获益,又可以被广泛使用。我唯一需要添加的(纯 ANSI)功能是按位逻辑运算(我的库为此被广泛打包,所以其他人似乎也同意)。
最后,如果你接受尽可能少地用 C 编写代码的论点,那么一个明显的下一步是
4. 如何用 Lua 编写 Lua 标准库?
我这里不是指像 StandardLibraryProposal 中那样的大量丰富的库集,而是指将一些核心功能构建到 Lua 中。这方面的候选者包括 assert 和 require 等函数,这些函数既没有功能性也没有性能原因迫使它们用 C 实现。
一个具体的例子:拥有一个更完整的 strftime 接口将很有用,这样你就可以用它来构建当前区域设置中月份或日期名称的列表。能够将 nil(NULL)传递给 setlocale 也会很有用。
列表实现 (NickTrout)
使用 Lua 表(tinsert()
、tremove()
和 getn()
)实现列表,需要在每个表中添加一个“n
”来保存包含的元素的最高索引。这种添加方法存在一些问题:-
- 命名冲突。例如,
n
可能是表中的一个元素。
- 迭代器会迭代
n
:-
list = { "a","b","c" }
tinsert(list,"d")
for _,v in list do print(v) end -- will print a,b,c,d,4
foreach(list, function(i,v) print(v) end) -- will print a,b,c,d,4
for i = 1,getn(list) do local v=list[i] print(v) end -- will print a,b,c,d
foreachi(list, function(i,v) print(v) end) -- will print a,b,c,d
- 第一种迭代列表的方法清晰方便,但由于
n
而失败。后两种方法确实有效,但我认为它们不够简洁(或效率不高?)。
现在已经添加了统一方法表,是否应该弃用 tinsert
、tremove
和 getn
,并添加一个 table()
方法,该方法创建一个具有类似于 Python 列表 和 Python 字典 的功能的表列表。它可能被称为“table”,而不是“list”或“dictionary”,因为其功能是两者的结合。例如:
t = {} -- table with no methods, "clean"
t = table() -- create table with tag/unified methods attached.
t = table{ a=1,b=7,c=8 } -- constructor with dictionary/associative items.
t = table{ a=1 ; "b","c" } -- mixed items.
t = table{ "a","b","c" } -- constructor with list.
t:append("d")
print( t:len() )
t= t:sort( function (a,b) return a>b end )
print( t:count("b") )
t:print() -- print items (rather than "<table>") and/or "print( t:tostring() )"
t:keys():print()
t:values():print()
for _,v in t do print(v) end -- and no "n"!
PeterPrade 关于标准库的一些想法
- 我认为应该解决命名空间问题,并展示一种方法,鼓励所有为 Lua 编写库的人采用这种方法。(例如,简单地添加一个包装表 - 例如字符串库的“str” - “str.find”而不是“strfind” - 虽然我不知道是否喜欢额外的运行时成本。如果你不喜欢额外的成本,命名约定几乎也能达到同样的效果(例如“str_find”))
- 我认为应该修复标准库的行为,以便能够编写简单的 Lua 包装器(任何 Lua 标准库函数都不应该使用传递给它的参数数量,或者应该将额外的 nil 等同于没有传递额外的参数)另请参见 TrailingNilParameters - 这很重要,因为许多人会采用标准库的风格。
- 添加一些用于表操作的工具(拆分 + 连接 (SplitJoin)、克隆、映射(使用函数映射表)、折叠等),甚至可以添加一种标准方法来使表持久化(一种非常幼稚的方法是 PersistentTables) 并修复 getn() 问题 (LuaTableSize)!
- 添加一些用于文件操作的工具(PetersStdLib 的 readfile+writefile - 我发现添加一些函数非常有用,这些函数接受文件名并返回文件内容的字符串,或者将字符串写入文件,这使得代码更加简洁)
我认为,与其这样,不如直接接受 Lua 的列表作为“原始列表”。这些原始列表由 VM 用于函数参数,当然也是表构造函数的结果。实现是公开的(n 字段)。许多应用程序将受益于更高层次的列表实现,正如你所提议的那样。但你肯定希望在使用任何类系统之上实现更高层次的列表。我认为 Lua 发行版不应该强加一个类系统。因此,这种事情应该属于一个更大的“在 Lua 之上”的库... --JohnBelmonte
某种基本的表功能,n
,需要保留,以便 for i=1,getn(t) ... end
能够在最基本的脚本中工作。无论如何,在表中添加 n
并不受欢迎,应该删除。上述表功能是作为标准库的可选组件还是扩展库的一部分,这是讨论的主题。我理解你关于它略微强加的观点,但由于它非常基础,我无法真正理解它强加的程度,以至于它是类系统的基础。--NickTrout
研讨会总结
研讨会以 Roberto Ierusalimschy 关于 Lua 的公开演讲开始。他强调了 Lua 的设计理念。演讲也表明,Lua 的小巧尺寸和快速执行是经过精心设计的实现的结果。
演讲结束后,以下人员参加了 Lua 库研讨会:
- Allyn Dimock <dimock at eecs.harvard.edu>
- Christian Carrillo <carrillo at tenebril.com>
- Christian Lindig <lindig at eecs.harvard.edu>
- John D. Ramsdell <ramsdell at linus.mitre.org>
- John Dias <dias at eecs.harvard.edu>
- Jon Eddy <eddy at eecs.harvard.edu>
- Noam Zeilberger <noam at eecs.harvard.edu>
- Norman Ramsey <nr at eecs.harvard.edu>
- Roberto Ierusalimschy <roberto at inf.puc-rio.br>
- Sukyoung Ryu <syryu at eecs.harvard.edu>
以下是不完整的 Lua 库研讨会讨论主题列表。也许其他与会者可以帮助补充完整。
- 我查看了 Lua 4.0 的 IO 库,并提出了一些更改建议。建议的核心是移除像 writeto 这样的隐式处理文件的函数。理由是,当处理多个文件时,它们不够通用。讨论主要围绕着不太激进的方法,以便普通用户仍然可以使用默认的输入和输出通道。
- http://www.eecs.harvard.edu/~lindig/papers/lua-iolib/
- http://www.eecs.harvard.edu/~lindig/papers/lua-iolib/slides.pdf
-
- 一个重要的讨论话题是命名空间管理。像 IO.open 这样的分层命名空间允许每个人贡献库并简化库之间的过渡。例如,目前尚不清楚库应该以面向对象风格编写还是以过程式风格编写。我们可以同时拥有两者,并在以后选择一个标准。与命名空间相关的問題包括:
- 编写模块 X.Y.Z,如何引用函数 X.Y.Z.f,而无需知道它是 X.Y.Z?本地模块 M 可以解决这个问题。
- 模块如何映射到文件系统?Python 的成功表明可以使用目录层次结构。讨论围绕着如何加载库和搜索路径。哪些可以用 Lua 编写,哪些必须进入内核?
- 在模块内部,是否有一种方法可以“打开”其他模块,以便可以访问它们的成员而无需使用点符号?似乎很难做到。
- 在运行时加载目标文件。共识是,这不是技术问题,而是政策问题。将实现它的微型目标特定模块放在哪里?John Ramsdell 建议从 Python 和 GNU Libtool 中寻找实现细节。
- 一种强制大型项目中变量声明的机制。出现了一种灵活的技术解决方案,但我没有完全理解。也许 Roberto 可以解释一下。
- Christian Carrillo 建议对 C API 进行一些更改,以更好地支持 Lua 线程环境。由于我不编写线程程序,细节我记不清了。
-- ChristianLindig?
最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2006 年 7 月 10 日下午 6:55 GMT (差异)