This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
api:non-standard-lua-libs:zh [2023/11/28 10:08] hfsr [协程操作] |
api:non-standard-lua-libs:zh [2023/12/10 14:52] (current) hfsr [基本函数] |
||
---|---|---|---|
Line 9: | Line 9: | ||
基本函数 | 基本函数 | ||
--------------- | --------------- | ||
- | 基本库中的[原函数](http://www.lua.org/manual/5.3/manual.html#6.1)是可用的,但有以下不同: | + | 基础库中的[原函数](http://www.lua.org/manual/5.3/manual.html#6.1)是可用的,但有以下不同: |
- `collectgarbage`**不可用**. | - `collectgarbage`**不可用**. | ||
Line 24: | Line 24: | ||
模块 | 模块 | ||
------- | ------- | ||
- | 模块部分已针对 OpenComputer 重新实现。效果应该跟[原本的](http://www.lua.org/manual/5.3/manual.html#6.3)相同,但它没有以下函数: | + | 模块部分已针对OpenComputer重新实现。效果应该跟[原本的](http://www.lua.org/manual/5.3/manual.html#6.3)相同,但它没有以下函数: |
- | - `package.config` 不存在且未使用。 | + | - `package.config`不存在且未使用。 |
- | - `package.cpath` 不存在且未使用。 | + | - `package.cpath`不存在且未使用。 |
- | - `package.loadlib` 未实现。 | + | - `package.loadlib`未实现。 |
- | 后两者不存在是因为OpenComputer不能加载C语言程序。 | + | 后两者不存在是因为OpenComputer不能加载C语言代码。 |
- | `require` 是一个在全局范围内可用的方法,也就是说,你不需要加载任何模块就能访问它,你可以在脚本的第一行就使用它(这是很常见的用法)。它的工作依赖于 `package` 库,因此我们就在这里对它进行介绍。 | + | `require`是在全局范围内可用的方法,也就是说,你不需要加载任何模块就能访问它,你可以在脚本的第一行就使用它(这是很常见的用法)。它的工作依赖于`package`库,因此我们就在这里对它进行介绍。 |
- | + | ||
- | * ''require(library: string): table'' | + | |
- | + | ||
- | 返回给定名称对应的 `library`。首先,如果该库先前已被加载过,那么 `package` 库已经缓存过它了,`require` 会返回该库的缓存版本。如果想要卸载库,参见 `package.loaded`。如果库没有被缓存,就会搜索 `package.path` 直到找到匹配的库。 | + | |
- | + | ||
- | * ''package.path'' | + | |
- | **我们建议用户不要修改默认的 package.path,相反地,用户应该把自定义库放入 /usr/lib/ 中。** | + | |
- | + | ||
- | 定义了一个供 `require` 遍历寻找库的搜索路径列表。它是一个用分号分隔的路径列表,使用 ‘?’ 作为传递给 `require` 库名的占位符。下面的例子会使它更容易理解 | + | |
- | + | ||
- | 默认 package.path: | + | |
- | + | ||
- | `/lib/?.lua;/usr/lib/?.lua;/home/lib/?.lua;./?.lua;/lib/?/init.lua;/usr/lib/?/init.lua;/home/lib/?/init.lua;./?/init.lua` | + | |
- | + | ||
- | 如果用户尝试导入 "foobar" | + | |
- | + | ||
- | `local foobar = require("foobar")` | + | |
- | + | ||
- | 以下是 `require` 为了执行 require("foobar") 而会去查找的文件的顺序。我们假设当前工作目录是 /tmp/,因为这样很 Cool! | + | |
+ | * ''require(library: string): table'' | ||
+ | 返回给定名称对应的`library`。首先,如果该库先前已被加载过,那么`package`库已经缓存它了,`require`会返回该库的缓存版本。如果想要卸载已预缓存的库,参见`package.loaded`。如果库没有被缓存,就会搜索`package.path`直到找到匹配的库。 | ||
+ | \\ | ||
+ | * ''package.path'' | ||
+ | **我们建议用户不要修改默认的`package.path`,相反地,用户应该把自定义库放入`/usr/lib/`中。** | ||
+ | 定义了一个供 `require` 遍历寻找库的搜索路径列表。它是一个用分号分隔的路径列表,使用`?`作为传递给`require`库名的占位符。下面的例子会使它更容易理解。 | ||
+ | \\ | ||
+ | 默认 package.path: | ||
+ | `/lib/?.lua;/usr/lib/?.lua;/home/lib/?.lua;./?.lua;/lib/?/init.lua;/usr/lib/?/init.lua;/home/lib/?/init.lua;./?/init.lua` | ||
+ | \\ | ||
+ | 如果用户尝试导入"foobar" | ||
+ | `local foobar = require("foobar")` | ||
+ | \\ | ||
+ | 以下是`require`为了执行require("foobar") 而会去查找的文件的顺序。为了有趣,我们假设当前工作目录是 /tmp/。 | ||
- /lib/foobar.lua | - /lib/foobar.lua | ||
- /usr/lib/foobar.lua | - /usr/lib/foobar.lua | ||
Line 61: | Line 56: | ||
- /home/lib/foobar/init.lua | - /home/lib/foobar/init.lua | ||
- /tmp/foobar/init.lua | - /tmp/foobar/init.lua | ||
- | + | \\ | |
- | * ''package.loaded'' | + | * ''package.loaded'' |
- | **修改 package.loaded 的行为并非标准操作** | + | **修改package.loaded的行为并非标准操作** |
- | + | 一个包含已缓存库源码的表,键为库的名称(即传入 `require` 的那个),值是缓存的库本身。将该表中的某个值设为`nil`的效果为从缓存中删除这个库。为了操作系统的正常运行,有些库会假定保持加载状态。 | |
- | 一个包含已被缓存的库的table,键为库的名称 (即传入 `require` 的那个),值是缓存的库本身。将该表中的某个值设为 `nil` 会从缓存中实实在在地删除这个库。有些库会假定保持加载状态,为了操作系统的正常运行。 | + | |
字符串操作 | 字符串操作 | ||
------------------- | ------------------- | ||
- | `string` 库内的[原函数](http://www.lua.org/manual/5.2/manual.html#6.4)均可用,没有任何变化。 | + | `string`库内的[原函数](http://www.lua.org/manual/5.2/manual.html#6.4)均可用,没有任何变化。 |
- | 注意,GPU API 中的函数可以接收 UTF-8 字符串,进而 `term.write` 和 `print` 也可以。为了帮助你处理 UTF-8 字符串,我们准备了一个额外的库,即 [[api:unicode:zh|Unicode API]]。 | + | 注意,GPU API中的函数工作于UTF-8字符串环境下,进而`term.write`和`print`也一样。为了帮助你处理UTF-8字符串,我们准备了一个额外的库,即[[api:unicode:zh|Unicode API]]。 |
表操作 | 表操作 | ||
------------------ | ------------------ | ||
- | `table` 库内的[原函数](http://www.lua.org/manual/5.2/manual.html#6.5)均可用,没有任何变化。 | + | `table`库内的[原函数](http://www.lua.org/manual/5.2/manual.html#6.5)均可用,没有任何变化。 |
数学函数 | 数学函数 | ||
Line 87: | Line 81: | ||
位操作 | 位操作 | ||
------------------ | ------------------ | ||
- | `bit32` 库内的[原函数](http://www.lua.org/manual/5.2/manual.html#6.7)均可用,没有任何变化。 | + | `bit32`库内的[原函数](http://www.lua.org/manual/5.2/manual.html#6.7)均可用,没有任何变化。 |
输入输出功能 | 输入输出功能 | ||
--------------------------- | --------------------------- | ||
- | `io` 库中大部分[原函数](http://www.lua.org/manual/5.2/manual.html#6.8)都被重新实现了,它们工作在已挂载的文件系统组件上。标准输入通过 `io.read` (同 `term.read` 和 `io.stdin:read`)读取。 标准输出通过 `io.write` (同 `term.write`、`io.stdout:write` 和 `print`)写入。标准错误通过 `io.stderr:write` 写入。 | + | `io`库中的[原函数](http://www.lua.org/manual/5.2/manual.html#6.8)都被很大程度上重新实现了,它们工作在已挂载的文件系统组件上。标准输入通过`io.read`(以及`term.read`和`io.stdin:read`)读取。 标准输出通过`io.write`(以及`term.write`、`io.stdout:write`和`print`)写入。标准错误通过`io.stderr:write`写入。 |
- | 大多数情况下,它们应该与标准 Lua 实现在*功能上*等价。也许它们返回的错误信息与原版Lua 不同,但大多数情况下原版Lua使用的也是与平台相关的 C 异常库,因此将这些用于程序逻辑无论如何都不是一个好主意。 | + | 大多数情况下,它们应该与标准Lua实现在**功能上**等价。也许它们返回的错误信息与原版Lua 不同,但大多数情况下原版Lua使用的也是基于平台的C异常库,因此将这些用于程序逻辑无论如何都不是一个好主意。 |
- | - `io.open(path, mode)` *不*支持 `+` 模式,即只支持 `r`、`w`、`a` 和 `rb` (允许使用`wb` 和 `ab` 模式,但是二进制模式对写入来说没有意义)。 注意, `io.open()` 返回 [[api:buffer:zh#实例方法|带缓冲IO流]],有比较智能的 api,如 `read("*a")` 可以读取整个文件,或者 `io.read("*l")` 可以读取一行。注意,带缓冲IO流(由 `io.open`返回的)可以是二进制模式或文本模式,而原始流(由 `filesystem.open`返回的)是且只能是二进制模式。 流是二进制模式还是文本模式只会影响到 `read`。 | + | - `io.open(path, mode)`**不支持**`+`模式,即只支持`r`、`w`、`a`和`rb`(允许使用`wb` 和 `ab` 模式,但是二进制模式对写入来说没有意义)。 |
+ | 注意,`io.open()`返回[[api:buffer:zh#实例方法|带缓冲IO流]],有比较智能的API,如`read("*a")` 可以读取整个文件,或者`io.read("*l")`可以读取一行。 | ||
+ | 还需注意,带缓冲IO流(由 `io.open`返回的)可以是二进制模式或文本模式,而原始流(由 `filesystem.open`返回的)是且只能是二进制模式。 流是二进制模式还是文本模式只会影响到 `read`。 | ||
`path` 是你想打开的文件的相对路径或绝对路径。 | `path` 是你想打开的文件的相对路径或绝对路径。 | ||
Line 101: | Line 97: | ||
`mode` 可以是 `nil` 或一个字符串, `nil` 默认为“r”。 | `mode` 可以是 `nil` 或一个字符串, `nil` 默认为“r”。 | ||
- | - **二进制模式** | + | - **二进制模式** |
- | + | `io.open(path, "rb")`或`filesystem.open(path)`返回的流是二进制格式。`filesystem.open(path, "rb")`的写法也可以,但从`filesystem.open`返回的流**永远**都是二进制模式。 | |
- | `io.open(path, "rb")` 或 `filesystem.open(path)` 返回的流是二进制格式。 `filesystem.open(path, "rb")` 也可以,但从 `filesystem.open` 返回的流**永远**都是二进制模式。 `stream:read(1)` 在二进制模式下读取一个字节。通过 `buffered_stream:read("*n")` 读取一个数值会把数据读成单字节的字符。(缓冲流从 `io.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`返回的,模式中没有使用"b"的流才是文本模式。例如`io.open(path)`和`io.open(path, "r")`。`filesystem.open`返回的任何句柄都不是文本模式下的流。 |
- | * `io.open(path, "r")` 相当于 `io.open(path)`,它以文本只读模式打开一个文件。 | + | 文本模式下的`stream:read(1)`读取单个Unicode字符。它可能是单字节的,或者甚至有3个字节,取决于文本。 |
- | * `io.open(path, "rb")` 以二进制只读模式打开一个文件。 | + | 通过`buffered_stream:read("*n")`读取一个数字值会将数据以unicode字符的形式进行读取。(带缓冲IO流是由 `io,open` 返回的,支持从流中解释数值) |
- | * `io.open(path, "w")` 删除文件的所有内容,以写模式打开文件。流是二进制模式还是文本模式并不影响写入。因此“w”在功能上等价于“wb”。 | + | \\ |
- | * `io.open(path, "a")` 以写模式打开一个文件并将文件句柄位置放在文件的末尾,这意味着下一次写入会追加到文件末尾。 | + | * `io.open(path, "r")` 相当于 `io.open(path)`,它以文本只读模式打开一个文件。 |
- | - `io.stdin` 从模拟的 stdin 中读取数据,它默认为 OpenOS shell 中的用户输入。注意 `io.read()` 是 `io.stdin:read()` 的简称,它们会被解析为完全相同的操作。 | + | \\ |
+ | * `io.open(path, "rb")` 以二进制只读模式打开一个文件。 | ||
+ | \\ | ||
+ | * `io.open(path, "w")` 删除文件的所有内容,以写模式打开文件。流是二进制模式还是文本模式并不影响写入。因此“w”在功能上等价于“wb”。 | ||
+ | \\ | ||
+ | * `io.open(path, "a")` 以写模式打开一个文件并将文件句柄位置放在文件的末尾,这意味着下一次写入会追加到文件末尾。 | ||
+ | \\ | ||
+ | - `io.stdin`从模拟的stdin中读取数据,它默认为OpenOS shell中的用户输入。注意`io.read()`是`io.stdin:read()`的简写,它们会被解析为完全相同的操作。 | ||
```lua | ```lua | ||
- | io.stdin:read() -- 从 std in 中读取 | + | io.stdin:read() -- 从stdin中读取 |
- | io.read() -- 也是从 std in 中读取 | + | io.read() -- 也是从stdin中读取 |
- | term.read() -- 也是从 std in 中读取 | + | term.read() -- 也是从stdin中读取 |
``` | ``` | ||
- | - `io.stdout` 将数据写到模拟的 stdout,默认在 gpu 上渲染。注意 `io.write()` 是 `io.stdout:write()` 的简称,它们会被解析为完全相同的操作。 | + | - `io.stdout`将数据写到模拟的stdout,默认为在GPU上渲染。注意`io.write()`是`io.stdout:write()`的简称,它们会被解析为完全相同的操作。 |
```lua | ```lua | ||
- | io.stdout:write("写入 stdout") | + | io.stdout:write("写入stdout") |
- | io.write("也是写入 stdout") | + | io.write("也是写入stdout") |
- | term.write("也是写入 stdout,但如果字符串超过屏幕分辨率允许的宽度,就会自动换行,就像这样--------------------------------------------------------------------------------------------------------------------------------#") | + | term.write("也是写入stdout,但如果字符串超过屏幕分辨率允许的宽度,就会自动换行") |
``` | ``` | ||
- | - `io.stderr` 将数据写到模拟的 stderr,默认在 gpu 上渲染,但如果主 GPU 和屏幕支持的话,会尝试用红色渲染。没有像 stdin 和 stdout 那样的使用 stderr 的快捷方式。 | + | - `io.stderr`将数据写到模拟的stderr,默认在GPU上渲染,但如果首选GPU和屏幕支持的话,会尝试用红色渲染。没有像stdin和stdout那样的使用stderr的快捷方式。 |
```lua | ```lua | ||
- | io.stderr:write("向 stderr 写入错误信息") | + | io.stderr:write("向stderr写入错误信息") |
``` | ``` | ||
操作系统功能 | 操作系统功能 | ||
--------------------------- | --------------------------- | ||
- | `os` 库内的[原函数](http://www.lua.org/manual/5.2/manual.html#6.9)已经被部分重新实现。 | + | `os`库内的[原函数](http://www.lua.org/manual/5.2/manual.html#6.9)已经被部分重新实现。 |
- | - `os.clock` 被重新实现为返回一个近似的 CPU 时间,也就是计算机在一个执行器线程中实际运行的时间。这与计算机运行时间*不*一样,获取此时间请参见[[api:computer:zh|computer.uptime]]。 | + | - `os.clock`被重新实现为返回近似CPU时间,也就是计算机在一个执行器线程中实际运行的时间。这与计算机运行时间**不一样**,获取此时间请参见[[api:computer:zh|computer.uptime]]。 |
- | - `os.date` 被重新实现为游戏中的时间,并支持大多数格式。 | + | \\ |
- | - `os.execute` 被重新实现,相当于从已挂载的文件系统中通过 `shell.execute` 启动程序。传入的字符串相当于在 shell 内输入的命令。 | + | - `os.date`被重新实现为使用游戏内时间,并支持大多数格式。 |
- | - `os.exit` 抛出一个错误并试图终止当前的 coroutine。 | + | \\ |
- | - `os.setenv` 添加 Lua shell 的环境变量。 | + | - `os.execute`被重新实现,相当于从已挂载的文件系统中通过`shell.execute`启动程序。传入的字符串相当于在 shell 内输入的命令。 |
- | - `os.remove` 是 `filesystem.remove` 的别名。 | + | \\ |
- | - `os.rename` 是 `filesystem.rename` 的别名。 | + | - `os.exit`抛出一个错误并试图终止当前的协程。 |
- | - `os.setlocale` *不*可用。 | + | \\ |
+ | - `os.setenv`添加Lua shell的环境变量。 | ||
+ | \\ | ||
+ | - `os.remove`是`filesystem.remove`的别名。 | ||
+ | \\ | ||
+ | - `os.rename`是`filesystem.rename`的别名。 | ||
+ | \\ | ||
+ | - `os.setlocale`**不可用**。 | ||
+ | \\ | ||
- `os.time` 被重新实现为返回自世界创建以来的游戏时间。 | - `os.time` 被重新实现为返回自世界创建以来的游戏时间。 | ||
- | 注意这个时间是以“游戏内的秒”为单位的。要获得世界创建起的时间刻(tick),需要将其乘以 `1000/60/60` (因为一天有24000个时间刻) 然后减去 6000。这个 6000 的偏移量不是随便设计的,它可以确保早上 6 点确实是那个时候。Minecraft莫名其妙地认为早上六点是零,可能是因为那是一个新游戏开始的时间…… | + | 注意这个时间是以“游戏内秒”为单位的。要获得世界创建起的tick数,需要将其乘以 `1000/60/60`(因为一天有24000个时间刻)然后减去6000。这个6000的偏移量不是随便设置的,它可以确保早上6点确实是早上6点。Minecraft莫名其妙地认为早上六点是零,可能是因为那是新游戏开始的时间…… |
+ | \\ | ||
- `os.tmpname` 已被重新实现,可以创建一个未使用的名字挂载到 `/tmp` 下。 | - `os.tmpname` 已被重新实现,可以创建一个未使用的名字挂载到 `/tmp` 下。 | ||
额外增加了一个函数: | 额外增加了一个函数: | ||
- | - `os.sleep(seconds: number)` 允许在指定的时间内暂停脚本。`os.sleep` 消耗事件,但注册的处理函数和线程在休眠时仍会接收事件。换句话说,在睡眠状态下,信号仍然会被处理函数处理,也就是说你无法在睡眠结束后拉取睡眠期间堆积的信号,因为没有信号会留在队列中(或者说至少不是全部信号)。 | + | - `os.sleep(seconds: number)`允许暂停脚本指定时间长度。`os.sleep`会消耗事件,但注册的处理函数和线程在休眠时仍会接收事件。换句话说,在睡眠状态下,信号仍然会被处理函数处理,也就是说你无法在睡眠结束后拉取睡眠期间堆积的信号,因为没有信号会留在队列中(或者说至少不是全部信号)。 |
- | [[api:computer:zh|computer(电脑) API]] 提供了一些类似这个类别的函数。 | + | 此类别的一些新函数可以在[[api:computer:zh|computer(电脑) API]]中找到。 |
调试 | 调试 | ||
----- | ----- | ||
- | 只实现了 `debug.traceback` 和 `debug.getinfo` (1.5.9 起),后者仅限被动信息。 | + | 只实现了`debug.traceback`和`debug.getinfo`(1.5.9起),仅限被动信息。 |
目录 | 目录 | ||
----------- | ----------- | ||
{{page>api:contents:zh&noheader&noeditbutton&nouser&nofooter}} | {{page>api:contents:zh&noheader&noeditbutton&nouser&nofooter}} |