元数据

Lua程序设计(第4版)

  •  Lua程序设计(第4版)|200
  • 书名: Lua程序设计(第4版)
  • 作者: 罗伯拖·鲁萨利姆斯奇
  • 简介: Lua语言是开源嵌入式脚本语言领域中独树一帜的一门语言,在包括游戏、嵌入式等领域具有不可替代的重要地位和极为广泛的应用,Lua也是学习编译原理、VM虚拟机等的重要参考和现实依据,Lua程序设计(第4版)结合作者多年的教学经验,更新到Lua5.3版本,让读者更好地吸收了该语言的特性。
  • 出版时间 2018-07-01 00:00:00
  • ISBN: 9787121338045
  • 分类: 计算机-编程设计
  • 出版社: 电子工业出版社
  • PC地址:https://weread.qq.com/web/reader/f9b3208071dbdd91f9b1ac6

高亮划线

1.1 程序段

  • 📌 dofile(“lib1.lua”)—加载文件 ^31186321-11-3111-3135
    • ⏱ 2024-02-21 00:35:05

1.3 全局变量

  • 📌 当把nil赋值给全局变量时,Lua会回收该全局变量(就像该全局变量从来没有出现过一样) ^31186321-13-711-754
    • ⏱ 2024-02-20 10:53:48

1.4 类型和值

  • 📌 函数type的返回值永远是一个字符串。

    • ⏱ 2024-02-20 17:58:29
  • 📌 一个全局变量在第一次被赋值前的默认值就是nil,而将nil赋值给全局变量则相当于将其删除。

    • ⏱ 2024-02-20 17:58:55

1.5 独立解释器

  • 📌 独立解释器(Stand-alone interpreter,由于源文件名为lua.c,所以也被称为lua.c;又由于可执行文件为lua,所以也被称为lua)是一个可以直接使用Lua语言的小程序。这一节介绍它的几个主要参数。

    • ⏱ 2024-02-20 18:00:27
  • 📌 -e参数允许我们直接在命令行中输入代码

    • ⏱ 2024-02-20 21:32:15
  • 📌 在POSIX系统下需要使用双引号,以防止Shell错误地解析括号。

    • ⏱ 2024-02-20 21:27:18
  • 📌 -l参数用于加载库

    • ⏱ 2024-02-20 21:32:18
  • 📌 -i参数用于在运行完其他命令行参数后进入交互模式

    • ⏱ 2024-02-20 21:32:29

3 数值

  • 📌 被称为integer的64位整型和被称为float的双精度浮点类型(注意,在本书中“float”不代表单精度类型) ^31186321-19-474-587
    • ⏱ 2024-02-21 11:11:38

3.1 数值常量

  • 📌 在少数情况下,当需要区分整型值和浮点型值时,可以使用函数math.type ^31186321-20-1399-1436
    • ⏱ 2024-02-21 11:13:50

3.2 算术运算

  • 📌 如果两个操作数都是整型值,那么结果也是整型值;否则,结果就是浮点型值。当操作数一个是整型值一个是浮点型值时,Lua语言会在进行算术运算前先将整型值转换为浮点型值

    • ⏱ 2024-02-21 11:21:26
  • 📌 floor除法的新算术运算符//

    • ⏱ 2024-02-21 11:21:41

3.4 数学库

  • 📌 数学库提供了三个取整函数:floor、ceil和modf。其中,floor向负无穷取整,ceil向正无穷取整,modf向零取整。

    • ⏱ 2024-02-21 11:37:24
  • 📌 modf还会返回小数部分作为第二个结果。

    • ⏱ 2024-02-21 11:37:47

3.5 表示范围

  • 📌 数学库中的常量定义了整型值的最大值(math.maxinteger)和最小值(math.mininteger)

    • ⏱ 2024-02-21 11:46:14
  • 📌 双精度浮点数对于大多数实际应用而言是足够大的,但是我们必须了解精度的限制。如果我们使用十位表示一个数,那么1/7会被取整到0.142857142。如果我们使用十位计算1/7*7,结果会是0.999999994而不是1。

    • ⏱ 2024-02-21 11:48:14

3.6 惯例

  • 📌 小于253(即9007199254740992)的所有整型值的表示与双精度浮点型值的表示一样,对于绝对值超过了这个值的整型值而言,在将其强制转换为浮点型值时可能导致精度损失

    • ⏱ 2024-02-21 11:53:11
  • 📌 通过与零进行按位或运算,可以把浮点型值强制转换为整型值

    • ⏱ 2024-02-21 11:54:00
  • 📌 另一种把数值强制转换为整型值的方式是使用函数math.tointeger,该函数会在输入参数无法转换为整型值时返回nil

    • ⏱ 2024-02-21 11:55:56

4 字符串

  • 📌 可以使用长度操作符(length operator)(#)获取字符串的长度 ^31186321-29-1451-1516
    • ⏱ 2024-02-21 15:17:40

4.2 长字符串/多行字符串

  • 📌 [===[

    • ⏱ 2024-02-21 15:26:45
  • 📌 可能引起歧义的二进制数据用十进制数值或十六进制的数值转义序列进行表示

    • ⏱ 2024-02-21 15:37:40

4.3 强制类型转换

  • 📌 当在数值后紧接着使用字符串连接时,必须使用空格将它们分开,否则Lua语言会把第一个点当成小数点。 ^31186321-32-829-877
    • ⏱ 2024-02-21 15:27:23

4.4 字符串标准库

  • 📌 函数string.sub(s,i,j)从字符串s中提取第i个到第j个字符(包括第i个和第j个字符,字符串的第一个字符索引为1)

    • ⏱ 2024-02-21 15:30:58
  • 📌 可以使用冒号操作符像调用字符串的一个方法那样调用字符串标准库中的所有函数

    • ⏱ 2024-02-21 15:32:54

4.5 Unicode编码

  • 📌 函数utf8.char和utf8.codepoint在UTF-8环境下等价于string.char和string.byte

    • ⏱ 2024-02-21 15:51:45
  • 📌 utf8库中大多数函数使用字节为索引。例如,调用string.codepo int(s,i,j)时i和j都会被当作字符串s中的字节位置。如果想使用字符位置作为索引,那么可以通过函数utf8.offset把字符位置转换为字节位置:

    • ⏱ 2024-02-21 15:52:02

5 表

  • 📌 Lua语言中的表本质上是一种辅助数组(associative array),这种数组不仅可以使用数值作为索引,也可以使用字符串或其他任意类型的值作为索引(nil除外)。

    • ⏱ 2024-02-21 16:53:22
  • 📌 对于一个表而言,当程序中不再有指向它的引用时,垃圾收集器会最终删除这个表并重用其占用的内存。

    • ⏱ 2024-02-21 16:54:10

5.1 表索引

  • 📌 同一个表中存储的值可以具有不同的类型索引

    • ⏱ 2024-02-21 16:56:04
  • 📌 当把表当作结构体使用时,可以把索引当作成员名称使用(a.name等价于a[“name”])。

    • ⏱ 2024-02-21 16:56:50
  • 📌 由于2和2.0的值相等,所以当它们被当作表索引使用时指向的是同一个表元素:

    • ⏱ 2024-02-21 17:11:54

5.3 数组、列表和序列

  • 📌 当向一个列表中写入了10行数据后,由于该列表的数值类型的索引为1,2,…,10,所以可以很容易地知道列表的长度就是10。这种技巧只有在列表中不存在空洞(hole)时(即所有元素均不为nil)才有效,此时我们把这种所有元素都不为nil的数组称为序列(sequence)。[插图]

    • ⏱ 2024-02-21 17:16:41
  • 📌 对于中间存在空洞(nil值)的列表而言,序列长度操作符是不可靠的,它只能用于序列(所有元素均不为nil的列表)。

    • ⏱ 2024-02-21 17:17:26
  • 📌 在多数情况下使用长度操作符是安全的。在确实需要处理存在空洞的列表时,应该将列表的长度显式地保存起来。

    • ⏱ 2024-02-21 17:20:05

5.4 遍历表

  • 📌 使用pairs迭代器遍历表中的键值对 ^31186321-40-416-434
    • ⏱ 2024-02-21 17:22:31

5.5 安全访问

  • 📌 对于表达式a or{},当a为nil时其结果是一个空表。因此,对于表达式(a or{}).b,当a为nil时其结果也同样是nil。 ^31186321-41-1566-1631
    • ⏱ 2024-02-21 17:25:27

5.6 表标准库

  • 📌 函数table.insert向序列的指定位置插入一个元素,其他元素依次后移。

    • ⏱ 2024-02-21 17:26:18
  • 📌 另一种特殊但常见的情况是调用insert时不指定位置,此时该函数会在序列的最后插入指定的元素,而不会移动任何元素。

    • ⏱ 2024-02-21 17:26:28
  • 📌 函数table.remove删除并返回序列指定位置的元素,然后将其后的元素向前移动填充删除元素后造成的空洞。如果在调用该函数时不指定位置,该函数会删除序列的最后一个元素。

    • ⏱ 2024-02-21 17:26:44

6 函数

  • 📌 函数调用时都需要使用一对圆括号把参数列表括起来。即使被调用的函数不需要参数,也需要一对空括号()。对于这个规则,唯一的例外就是,当函数只有一个参数且该参数是字符串常量或表构造器时,括号是可选的

    • ⏱ 2024-02-22 10:26:31
  • 📌 调用函数时使用的参数个数可以与定义函数时使用的参数个数不一致。Lua语言会通过抛弃多余参数和将不足的参数设为nil的方式来调整参数的个数。

    • ⏱ 2024-02-22 10:28:50

6.1 多返回值

  • 📌 Lua语言中一种与众不同但又非常有用的特性是允许一个函数返回多个结果(Multiple Results)

    • ⏱ 2024-02-22 10:29:46
  • 📌 Lua语言根据函数的被调用情况调整返回值的数量。

    • ⏱ 2024-02-22 10:30:41
  • 📌 在多重赋值中,如果一个函数没有返回值或者返回值个数不够多,那么Lua语言会用nil来补充缺失的值

    • ⏱ 2024-02-22 10:34:00
  • 📌 当在表达式中调用foo2时,Lua语言会把其返回值的个数调整为1

    • ⏱ 2024-02-22 10:35:31

6.2 可变长参数函数

  • 📌 参数列表中的三个点(…)表示该函数的参数是可变长的。

    • ⏱ 2024-02-29 15:28:25
  • 📌 三个点组成的表达式称为可变长参数表达式(vararg expression)

    • ⏱ 2024-02-23 09:35:54
  • 📌 另一种遍历函数的可变长参数的方法是使用函数select。函数select总是具有一个固定的参数selector,以及数量可变的参数。如果selector是数值n,那么函数select则返回第n个参数后的所有参数;否则,selector应该是字符串”#“,以便函数select返回额外参数的总数。

    • ⏱ 2024-02-29 15:45:57

6.3 函数table.unpack

  • 📌 table.unpack

    • ⏱ 2024-02-29 13:42:23
  • 📌 多重返回值还涉及一个特殊的函数table.unpack。该函数的参数是一个数组,返回值为数组内的所有元素

    • ⏱ 2024-02-29 13:42:40
  • 📌 通常,函数table.unpack使用长度操作符获取返回值的个数,因而该函数只能用于序列。不过,如果有需要,也可以显式地限制返回元素的范围

    • ⏱ 2024-02-29 14:02:29

6.4 正确的尾调用

  • 📌 Lua语言中有关函数的另一个有趣的特性是,Lua语言是支持尾调用消除(tail-call elimination)的。

    • ⏱ 2024-02-29 14:02:48
  • 📌 当一个函数的最后一个动作是调用另一个函数而没有再进行其他工作时,就形成了尾调用

    • ⏱ 2024-02-29 15:04:30
  • 📌 因此,在尾调用之后,程序也就不需要在调用栈中保存有关调用函数的任何信息。当g返回时,程序的执行路径会直接返回到调用f的位置。在一些语言的实现中,例如Lua语言解释器,就利用了这个特点,使得在进行尾调用时不使用任何额外的栈空间。

    • ⏱ 2024-02-29 15:04:52
  • 📌 由于尾调用不会使用栈空间,所以一个程序中能够嵌套的尾调用的数量是无限的。

    • ⏱ 2024-02-29 15:03:32
  • 📌 关于尾调用消除的一个重点就是如何判断一个调用是尾调用。很多函数调用之所以不是尾调用,是由于这些函数在调用之后还进行了其他工作。

    • ⏱ 2024-02-29 15:08:02
  • 📌 只有形如returnfunc(args)的调用才是尾调用。

    • ⏱ 2024-02-29 15:10:55

7.1 简单I/O模型

  • 📌 函数io.write可以读取任意数量的字符串(或者数字)并将其写入当前输出流。

    • ⏱ 2024-03-01 10:07:30
  • 📌 函数io.read可以从当前输入流中读取字符串,其参数决定了要读取的数据

    • ⏱ 2024-03-01 10:08:06
  • 📌 因为Lua语言可以高效地处理长字符串,所以在Lua语言中编写过滤器(filter)的一种简单技巧就是将整个文件读取到一个字符串中,然后对字符串进行处理

    • ⏱ 2024-03-01 10:08:29

7.2 完整I/O模型

  • 📌 使用函数io.open来打开一个文件 ^31186321-52-519-537
    • ⏱ 2024-03-01 10:46:04

7.4 其他系统调用

  • 📌 函数os.exit用于终止程序的执行

    • ⏱ 2024-03-01 10:20:34
  • 📌 函数os.execute用于运行系统命令,它等价于C语言中的函数system。

    • ⏱ 2024-03-01 10:20:44

8.1 局部变量和代码块

  • 📌 Lua语言中的变量在默认情况下是全局变量,所有的局部变量在使用前必须声明。与全局变量不同,局部变量的生效范围仅限于声明它的代码块。 ^31186321-57-417-482
    • ⏱ 2024-03-01 16:03:35

8.2 控制结构

  • 📌 if语句先测试其条件,并根据条件是否满足执行相应的then部分或else部分。else部分是可选的。

    • ⏱ 2024-03-01 16:07:20
  • 📌 如果要编写嵌套的if语句,可以使用elseif。它类似于在else后面紧跟一个if,但可以避免重复使用end:

    • ⏱ 2024-03-01 16:07:32
  • 📌 while循环会重复执行其循环体。Lua语言先测试while语句的条件,若条件为假则循环结束;否则,Lua会执行循环体并不断地重复这个过程

    • ⏱ 2024-03-01 16:07:51
  • 📌 repeat–until语句会重复执行其循环体直到条件为真时结束。由于条件测试在循环体之后执行,所以循环体至少会执行一次。

    • ⏱ 2024-03-01 16:07:45
  • 📌 泛型for遍历迭代函数返回的所有值,例如我们已经在很多示例中看到过的pairs、ipairs和io.lines等。

    • ⏱ 2024-03-01 16:19:10

8.3 break、return和goto

  • 📌 break和return语句用于从当前的循环结构中跳出,goto语句则允许跳转到函数中的几乎任何地方。

    • ⏱ 2024-03-01 16:20:56
  • 📌 在Lua语言中,goto语句的语法非常传统,即保留字goto后面紧跟着标签名,标签名可以是任意有效的标识符。标签的语法稍微有点复杂:标签名称前后各紧跟两个冒号,形如::name::。这个复杂的语法是有意而为的,主要是为了在程序中醒目地突出这些标签。

    • ⏱ 2024-03-01 16:25:32

第2部分 编程实操

  • 📌 “第一类值”意味着Lua语言中的函数与其他常见类型的值(例如数值和字符串)具有同等权限

    • ⏱ 2024-03-01 16:34:24
  • 📌 一个程序可以将某个函数保存到变量中(全局变量和局部变量均可)或表中,也可以将某个函数作为参数传递给其他函数,还可以将某个函数作为其他函数的返回值返回。

    • ⏱ 2024-03-01 16:34:52

9.1 函数是第一类值

  • 📌 在Lua语言中,所有的函数都是匿名的(anonymous) ^31186321-62-1586-1615
    • ⏱ 2024-03-01 17:19:17

9.2 非全局函数

  • 📌 数不仅可以被存储在全局变量中,还可以被存储在表字段和局部变量中。

    • ⏱ 2024-03-01 17:24:39
  • 📌 局部的fact尚未定义。因此,这个表达式会尝试调用全局的fact而非局部的fact

    • ⏱ 2024-03-01 17:26:10

9.3 词法定界

  • 📌 从技术上讲,Lua语言中只有闭包而没有函数。函数本身只是闭包的一种原型。不过尽管如此,只要不会引起混淆,我们就仍将使用术语“函数”来指代闭包。

    • ⏱ 2024-03-01 17:48:29
  • 📌 由于函数可以被保存在普通变量中,因此在Lua语言中可以轻松地重新定义函数,甚至是预定义函数。这种机制也正是Lua语言灵活的原因之一。通常,当重新定义一个函数的时候,我们需要在新的实现中调用原来的那个函数。

    • ⏱ 2024-03-01 17:56:42
  • 📌 相对于提供一套大而全(one-size-fits-all)的解决方案,Lua语言提供的是一套“元机制(meta-mechanism)”,借助这种机制可以根据特定的安全需求来裁剪具体的运行时环境

    • ⏱ 2024-03-01 18:00:47

10.1 模式匹配的相关函数

  • 📌 函数string.find

    • ⏱ 2024-03-04 09:59:18
  • 📌 函数string.find用于在指定的目标字符串中搜索指定的模式。

    • ⏱ 2024-03-04 09:59:23

20 元表和元方法

  • 📌 但是,我们无法将两个表相加,无法对函数作比较,也无法调用一个字符串,除非使用元表。

    • ⏱ 2024-03-04 10:41:49
  • 📌 元表可以修改一个值在面对一个未知操作时的行为。

    • ⏱ 2024-03-04 10:41:55
  • 📌 元表是面向对象领域中的受限制类。

    • ⏱ 2024-03-04 10:42:57
  • 📌 元表定义的是实例的行为。

    • ⏱ 2024-03-04 10:43:13
  • 📌 Lua语言中的每一个值都可以有元表。每一个表和用户数据类型都具有各自独立的元表,而其他类型的值则共享对应类型所属的同一个元表。

    • ⏱ 2024-03-04 10:45:17
  • 📌 使用函数setmetatable来设置或修改任意表的元表

    • ⏱ 2024-03-04 10:45:37
  • 📌 字符串标准库为所有的字符串都设罝了同一个元表,而其他类型在默认情况中都没有元表:

    • ⏱ 2024-03-04 10:51:04
  • 📌 一个表可以成为任意值的元表;一组相关的表也可以共享一个描述了它们共同行为的通用元表;一个表还可以成为它自己的元表,用于描述其自身特有的行为。总之,任何配置都是合法的。

    • ⏱ 2024-03-04 10:51:15

20.1 算术运算相关的元方法

  • 📌 当一个表达式中混合了两种具有不同元表的值时

    • ⏱ 2024-03-04 11:02:11
  • 📌 如果第一个值有元表且元表中存在所需的元方法,那么Lua语言就使用这个元方法,与第二个值无关;如果第二个值有元表且元表中存在所需的元方法,Lua语言就使用这个元方法;否则,Lua语言就抛出异常。

    • ⏱ 2024-03-04 11:02:20
  • 📌 Lua语言不关心这些混合类型,但我们在实现中需要关心混合类型

    • ⏱ 2024-03-04 11:02:55

20.2 关系运算相关的元方法

  • 📌 在Lua语言的老版本中,Lua语言会通过将ab转换为not(b<a)来把所有的关系运算符转化为一个关系运算符。不过,这种转化在遇到部分有序(partial order)时就会不正确。所谓部分有序是指,并非所有类型的元素都能够被正确地排序。

    • ⏱ 2024-03-04 11:04:06
  • 📌 NaN代表未定义的值,例如0/0的结果就是NaN。标准规定任何涉及NaN的比较都应返回假,这就意味着NaNx永远为假,x<NaN也为假。

    • ⏱ 2024-03-04 11:04:00
  • 📌 相等比较有一些限制。如果两个对象的类型不同,那么相等比较操作不会调用任何元方法而直接返回false。因此,不管元方法如何,集合永远不等于数字。

    • ⏱ 2024-03-04 11:05:56

20.3 库定义相关的元方法

  • 📌 函数setmetatable和getmetatable也用到了元方法,用于保护元表。 ^31186321-125-1563-1605
    • ⏱ 2024-03-04 11:07:39

20.4 表相关的元方法

  • 📌 __index元方法

    • ⏱ 2024-03-04 11:09:18
  • 📌 正如我们此前所看到的,当访问一个表中不存在的字段时会得到nil。这是正确的,但不是完整的真相。实际上,这些访问会引发解释器查找一个名为__index的元方法。如果没有这个元方法,那么像一般情况下一样,结果就是nil;否则,则由这个元方法来提供最终结果。

    • ⏱ 2024-03-04 11:09:41
  • 📌 使用元方法__index来实现继承是很普遍的方法。虽然被叫作方法,但元方法__index不一定必须是一个函数,它还可以是一个表。当元方法是一个函数时,Lua语言会以表和不存在的键为参数调用该函数,正如我们刚刚所看到的。当元方法是一个表时,Lua语言就访问这个表。

    • ⏱ 2024-03-04 11:10:59
  • 📌 将一个表用作__index元方法为实现单继承提供了一种简单快捷的方法。虽然将函数用作元方法开销更昂贵,但函数却更加灵活:我们可以通过函数来实现多继承、缓存及其他一些变体。

    • ⏱ 2024-03-04 11:11:18
  • 📌 如果我们希望在访问一个表时不调用__index元方法,那么可以使用函数rawget。调用rawget(t,i)会对表t进行原始(raw)的访问,即在不考虑元表的情况下对表进行简单的访问。

    • ⏱ 2024-03-04 11:20:58
  • 📌 元方法__newindex与__index类似,不同之处在于前者用于表的更新而后者用于表的查询。

    • ⏱ 2024-03-04 11:21:10
  • 📌 对一个表中不存在的索引赋值时,解释器就会查找__newindex元方法:如果这个元方法存在,那么解释器就调用它而不执行赋值。像元方法__index一样,如果这个元方法是一个表,解释器就在此表中执行赋值,而不是在原始的表中进行赋值。

    • ⏱ 2024-03-04 11:21:44
  • 📌 调用rawset(t,k,v)来等价于t[k]=v,但不涉及任何元方法。

    • ⏱ 2024-03-04 11:21:34
  • 📌 一个普通表中所有字段的默认值都是nil。通过元表,可以很容易地修改这个默认值

    • ⏱ 2024-03-04 11:22:39
  • 📌 在调用setDefault后,任何对表tab中不存在字段的访问都将调用它的__index元方法,而这个元方法会返回零(这个元方法中的值是d)。

    • ⏱ 2024-03-04 11:23:06
  • 📌 为了能够使所有的表都使用同一个元表,可以使用一个额外的字段将每个表的默认值存放到表自身中。

    • ⏱ 2024-03-04 11:24:28
  • 📌 还有一种方法可以将每个表与其默认值关联起来,称为对偶表示

    • ⏱ 2024-03-04 11:26:20
  • 📌 不过,为了正确地实现这种做法,我们还需要一种特殊的表,称为弱引用表(weak table)

    • ⏱ 2024-03-04 11:27:56
  • 📌 假设我们要跟踪对某个表的所有访问。由于__index和__newindex元方法都是在表中的索引不存在时才有用,因此,捕获对一个表所有访问的唯一方式是保持表是空的。如果要监控对一个表的所有访问,那么需要为真正的表创建一个代理(proxy)。

    • ⏱ 2024-03-04 11:29:37
  • 📌 使用代理的概念可以很容易地实现只读的表,需要做的只是跟踪对表的更新操作并抛出异常即可。对于元方法__index,由于我们不需要跟踪查询,所以可以直接使用原来的表来代替函数。这样做比把所有的查询重定向到原来的表上更简单也更有效率

    • ⏱ 2024-03-04 11:31:07

21 面向对象(Object-Oriented)编程

  • 📌 从很多意义上讲,Lua语言中的一张表就是一个对象。

    • ⏱ 2024-03-04 10:34:14
  • 📌 表与对象一样,可以拥有状态。其次,表与对象一样,拥有一个与其值无关的的标识(self[插图]);特别地,两个具有相同值的对象(表)是两个不同的对象,而一个对象可以具有多个不同的值;最后,表与对象一样,具有与创建者和被创建位置无关的生命周期。

    • ⏱ 2024-03-04 10:36:00
  • 📌 另一种更加有原则的方法是对操作的接受者(receiver)进行操作。

    • ⏱ 2024-03-04 10:36:55
  • 📌 冒号的作用是在一个方法调用中增加一个额外的实参,或在方法的定义中增加一个额外的隐藏形参。

    • ⏱ 2024-03-04 10:38:17

21.1 类(Class)

  • 📌 大多数面向对象语言提供了类的概念,类在对象的创建中扮演了模子(mold)的作用。在这些语言中,每个对象都是某个特定类的实例(instance)。

    • ⏱ 2024-03-04 10:38:45
  • 📌 我们可以参考基于原型的语言(prototype-based language)中的一些做法来在Lua语言中模拟类,例如Self语言(JavaScript采用的也是这种方式)。

    • ⏱ 2024-03-04 10:38:55
  • 📌 原型也是一种普通的对象,当对象(类的实例)遇到一个未知操作时会首先在原型中查找。要在这种语言中表示一个类,我们只需要创建一个专门被用作其他对象(类的实例)的原型对象即可。

    • ⏱ 2024-03-04 11:35:32
  • 📌 对于这种模式,我们可以进行两个小改进。第一种改进是,不创建扮演元表角色的新表而是把表Account直接用作元表。第二种改进是,对new方法也使用冒号语法。

    • ⏱ 2024-03-04 11:37:52
  • 📌 表达式b.balance求值后等于零,且该方法给b.balance赋了初始的金额。由于此时b有了它自己的balance字段,因此后续对b.balance的访问就不会再涉及元方法了。

    • ⏱ 2024-03-04 11:40:18

21.3 多重继承(Multiple Inheritance)

  • 📌 这种实现的关键在于把一个函数用作__index元方法。 ^31186321-131-616-643
    • ⏱ 2024-03-04 11:44:40

读书笔记

1.6 练习

划线评论

  • 📌 请编写一个可以打印出脚本自身名称的程序(事先不知道脚本自身的名称)。 ^262631416-7P8c92u5l
    • 💭 print(arg[0])
    • ⏱ 2024-02-21 01:03:33

2.1 练习

划线评论

  • 📌 修改八皇后问题的程序,使其在输出第一个解后即停止运行 ^262631416-7P8PUBj6Z
    • 💭 放置皇后棋子的代码中,加上剪枝,如果符合要求就返回True
    • ⏱ 2024-02-21 11:10:45

3.1 数值常量

划线评论

  • 📌 Lua语言像其他语言一样也支持以0x开头的十六进制常量。与其他很多编程语言不同,Lua语言还支持十六进制的浮点数,这种十六进制浮点数由小数部分和以p或P开头的指数部分组成。 ^262631416-7P8QszyT3
    • 💭 a.b是十六进制数,其中a等于十进制的10,而.b表示十六进制的分数部分,即b(十六进制的11)除以16。p表示2的幂次,这是一个指数,表示浮点数应该乘以2的多少次幂。
    • ⏱ 2024-02-21 11:19:07

3.9 练习

划线评论

  • 📌 当分母是10的整数次幂时,数值12.7与表达式127/10相等。能否认为当分母是2的整数次幂时,这是一种通用规律?对于数值5.5情况又会怎样呢? ^262631416-7P92HpItY
    • 💭 可以得。 12.7 可以用 0x19.6666666666666p-1 表示,5.5 用 11/2 表示。
    • ⏱ 2024-02-21 14:26:00

划线评论

  • 📌 利用函数math.random编写一个生成遵循正态分布(高斯分布)的伪随机数发生器。 ^262631416-7P95ZYAnE
    • 💭 Box-Muller 转换
    • ⏱ 2024-02-21 15:16:22

4.6 练习

划线评论

  • 📌 练习4.1 ^262631416-7P97uqu0f
    • 💭 1.使用[=[]=]来包裹多行字符串 2.使用转义字符
    • ⏱ 2024-02-21 15:39:08

本书评论