大部分Lua标准库都是可用的,尽管其中的一些只是部分可用或是重新实现的——这意味着其行为可能会略有不同。请参阅Lua 5.3 手册(英文)中关于标准库的文档。
对“重新实现”的描述是基于OpenOS的,其他自定义的操作系统可能会有不同的细节。
本页将尝试列出所有与标准库的差异。
基础库中的原函数是可用的,但有以下不同:
collectgarbage
不可用.load
在默认情况下只能用来加载文本,不支持二进制或编译过的代码。注意,配置文件中可以启用字节码的加载,但非常不推荐这样做,因为这是一个重大安全风险。print
、io.write
、io.stdout:write
和term.write
都向stdout(标准输出)推送字符串,这在大多数情况下都指gpu渲染,即输出到屏幕上。
coroutine
库内的原函数均可用,并没有可见的差异。
注意,暴露给用户使用的coroutine.resume
和coroutine.yield
实现是封装过的,它们负责中止在一定时间(见配置文件)后还没有yield的代码,还可以区分系统产生的yield和用户产生的yield(系统会产生“bubble”,例如在关闭命令行或调用组件 API 时)。然而这不应该从用户代码层面被注意到。如果被注意到了,应该被认为是bug。
模块部分已针对OpenComputer重新实现。效果应该跟原本的相同,但它没有以下函数:
package.config
不存在且未使用。package.cpath
不存在且未使用。package.loadlib
未实现。后两者不存在是因为OpenComputer不能加载C语言代码。
require
是在全局范围内可用的方法,也就是说,你不需要加载任何模块就能访问它,你可以在脚本的第一行就使用它(这是很常见的用法)。它的工作依赖于package
库,因此我们就在这里对它进行介绍。
require(library: string): table
library
。首先,如果该库先前已被加载过,那么package
库已经缓存它了,require
会返回该库的缓存版本。如果想要卸载已预缓存的库,参见package.loaded
。如果库没有被缓存,就会搜索package.path
直到找到匹配的库。package.path
package.path
,相反地,用户应该把自定义库放入/usr/lib/
中。require
遍历寻找库的搜索路径列表。它是一个用分号分隔的路径列表,使用?
作为传递给require
库名的占位符。下面的例子会使它更容易理解。/lib/?.lua;/usr/lib/?.lua;/home/lib/?.lua;./?.lua;/lib/?/init.lua;/usr/lib/?/init.lua;/home/lib/?/init.lua;./?/init.lua
local foobar = require("foobar")
require
为了执行require(“foobar”) 而会去查找的文件的顺序。为了有趣,我们假设当前工作目录是 /tmp/。
package.loaded
require
的那个),值是缓存的库本身。将该表中的某个值设为nil
的效果为从缓存中删除这个库。为了操作系统的正常运行,有些库会假定保持加载状态。
string
库内的原函数均可用,没有任何变化。
注意,GPU API中的函数工作于UTF-8字符串环境下,进而term.write
和print
也一样。为了帮助你处理UTF-8字符串,我们准备了一个额外的库,即Unicode API。
table
库内的原函数均可用,没有任何变化。
math
库中的原函数均可用,但有一点改动。
math.random
为每个 Lua state和计算机使用一个单独的 java.util.Random
实例。math.randomseed
也被应用于对应的实例。
bit32
库内的原函数均可用,没有任何变化。
io
库中的原函数都被很大程度上重新实现了,它们工作在已挂载的文件系统组件上。标准输入通过io.read
(以及term.read
和io.stdin:read
)读取。 标准输出通过io.write
(以及term.write
、io.stdout:write
和print
)写入。标准错误通过io.stderr:write
写入。
大多数情况下,它们应该与标准Lua实现在功能上等价。也许它们返回的错误信息与原版Lua 不同,但大多数情况下原版Lua使用的也是基于平台的C异常库,因此将这些用于程序逻辑无论如何都不是一个好主意。
io.open(path, mode)
不支持+
模式,即只支持r
、w
、a
和rb
(允许使用wb
和 ab
模式,但是二进制模式对写入来说没有意义)。io.open()
返回带缓冲IO流,有比较智能的API,如read("*a")
可以读取整个文件,或者io.read("*l")
可以读取一行。io.open
返回的)可以是二进制模式或文本模式,而原始流(由 filesystem.open
返回的)是且只能是二进制模式。 流是二进制模式还是文本模式只会影响到 read
。
path
是你想打开的文件的相对路径或绝对路径。
mode
可以是 nil
或一个字符串, nil
默认为“r”。
io.open(path, "rb")
或filesystem.open(path)
返回的流是二进制格式。filesystem.open(path, "rb")
的写法也可以,但从filesystem.open
返回的流永远都是二进制模式。stream:read(1)
读取一个字节。buffered_stream:read("*n")
读取一个数字值会将数据以单字节字符的形式读取。(缓冲流从 io.open
返回,并支持从流中解释数值)io.open
返回的,模式中没有使用“b”的流才是文本模式。例如io.open(path)
和io.open(path, "r")
。filesystem.open
返回的任何句柄都不是文本模式下的流。stream:read(1)
读取单个Unicode字符。它可能是单字节的,或者甚至有3个字节,取决于文本。buffered_stream:read("*n")
读取一个数字值会将数据以unicode字符的形式进行读取。(带缓冲IO流是由 io,open
返回的,支持从流中解释数值)io.open(path, "r")
相当于 io.open(path)
,它以文本只读模式打开一个文件。io.open(path, "rb")
以二进制只读模式打开一个文件。io.open(path, "w")
删除文件的所有内容,以写模式打开文件。流是二进制模式还是文本模式并不影响写入。因此“w”在功能上等价于“wb”。io.open(path, "a")
以写模式打开一个文件并将文件句柄位置放在文件的末尾,这意味着下一次写入会追加到文件末尾。io.stdin
从模拟的stdin中读取数据,它默认为OpenOS shell中的用户输入。注意io.read()
是io.stdin:read()
的简写,它们会被解析为完全相同的操作。io.stdin:read() -- 从stdin中读取 io.read() -- 也是从stdin中读取 term.read() -- 也是从stdin中读取
io.stdout
将数据写到模拟的stdout,默认为在GPU上渲染。注意io.write()
是io.stdout:write()
的简称,它们会被解析为完全相同的操作。io.stdout:write("写入stdout") io.write("也是写入stdout") term.write("也是写入stdout,但如果字符串超过屏幕分辨率允许的宽度,就会自动换行")
io.stderr
将数据写到模拟的stderr,默认在GPU上渲染,但如果首选GPU和屏幕支持的话,会尝试用红色渲染。没有像stdin和stdout那样的使用stderr的快捷方式。io.stderr:write("向stderr写入错误信息")
os
库内的原函数已经被部分重新实现。
os.date
被重新实现为使用游戏内时间,并支持大多数格式。os.execute
被重新实现,相当于从已挂载的文件系统中通过shell.execute
启动程序。传入的字符串相当于在 shell 内输入的命令。os.exit
抛出一个错误并试图终止当前的协程。os.setenv
添加Lua shell的环境变量。os.remove
是filesystem.remove
的别名。os.rename
是filesystem.rename
的别名。os.setlocale
不可用。os.time
被重新实现为返回自世界创建以来的游戏时间。
注意这个时间是以“游戏内秒”为单位的。要获得世界创建起的tick数,需要将其乘以 1000/60/60
(因为一天有24000个时间刻)然后减去6000。这个6000的偏移量不是随便设置的,它可以确保早上6点确实是早上6点。Minecraft莫名其妙地认为早上六点是零,可能是因为那是新游戏开始的时间……os.tmpname
已被重新实现,可以创建一个未使用的名字挂载到 /tmp
下。额外增加了一个函数:
os.sleep(seconds: number)
允许暂停脚本指定时间长度。os.sleep
会消耗事件,但注册的处理函数和线程在休眠时仍会接收事件。换句话说,在睡眠状态下,信号仍然会被处理函数处理,也就是说你无法在睡眠结束后拉取睡眠期间堆积的信号,因为没有信号会留在队列中(或者说至少不是全部信号)。此类别的一些新函数可以在computer(电脑) API中找到。
只实现了debug.traceback
和debug.getinfo
(1.5.9起),仅限被动信息。