哈佛大学 Lua 库设计研讨会,2 月 19 日星期二
嵌入式编程语言 Lua [1] 的设计,体现了设计者近十年来细致的思考和关注。然而,陪伴 Lua 的标准库并未得到同等的关注。作为该语言的用户,我们有兴趣改进该库。因此,我们正在举办一个(短暂的)为期一天的研讨会,以制定改进该库的建议。向后兼容性不是必需的;如果我们愿意,可以抛弃一切从头开始!(但是,我们将坚持当前语言定义——只有库可以商榷。)我们很幸运能有 Lua 的首席设计师之一 RobertoIerusalimschy 与我们同在。我们预计工作时间约为上午 10 点到下午 4 点,中间有短暂的午餐休息。这是一个工作会议,而不是一个演讲和小组讨论的日子,我们希望从中产生非常具体、明确的建议给 Lua 团队。因此, enrollment 将限制在 20 人左右。
如果您想参加本次研讨会,请告知我们。请发送电子邮件至 Christian Lindig [lindig@eecs.harvard.edu]。我们希望在 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 库可能不适用于特定嵌入式平台)。
- 我写第一个版本时忘记了一件事:如果 math 库能够利用支持 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()` 方法,该方法创建的列表功能类似于 PythonLists 和 PythonDictionaries 的结合。它可能被称为“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——这一点很重要,因为许多人将采纳标准库的风格。
- 添加更多用于表操作的工具(split + join (SplitJoin), clone, map(使用函数映射表), collapse 等)也许还可以添加一种使表持久化的标准方法(一种非常幼稚的方法是 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?
RecentChanges · preferences
编辑 · 历史
最后编辑于 2006 年 7 月 10 日下午 12:55 GMT (diff)