分类 第二章 类型与值 下的文章

1、在 lua 中,函数是作为‘第一类值’来看待的。(表示函数可以存储在变量中,可以通过参数传递给其他函数,还可以作为其他函数的返回值)

2、

  • 为了给一个函数添加新的功能,程序可以重新定义该函数。
  • 运行一些不受信任的代码时,可以先删除某些函数,从而创建一个安全的运行环境。
  • Lua 对’函数式编程‘也提供了良好的支持。如,允许在某些词法域中编写嵌套的函数。

    3、Lua 既可以调用以自身 Lua 语言编写的函数,又可以调用以 c语言 编写的函数

    4、Lua 所有的标准库都是用 c语言 写的,标准库中包含对

  • 字符串的操作
  • table 的操作
  • I/O
  • 操作系统的功能调用
  • 数学函数
  • 调试函数

    5、应用程序也可以用 c语言 来定义其他函数

1、由于 userdata 类型可以将任意的 c语言数据 存储到 Lua变量 中。在 Lua 中,这种类型没有太多的预定义的操作,只能进行 赋值 和 相等性测试

userdata 用于表示一种由 应用程序 或者 c语言库 所创建的新类型,如,标准的 I/O库 就用 userdata 来表示文件

2、thread -- 协同程序

1、实现了关联数组(具有特殊索引方式的数组)

不仅可以通过整数来索引它,还可以使用字符串其他类型的值(除了nil)来索引它

2、没有固定大小,可以动态地添加任意数量的元素到一个 table 中

3、通过 table 来表示模块、包、对象

如,输入 io.read() 时,对于 lua,表示使用字符串 "read" 作为 key 来索引 "table.io"

4、在 lua 中,table 是"对象",可以将一个 table 想象成一种动态分配的对象。程序仅持有一个对他们的引用(或指针)。lua 不会暗中产生 table 的副本或者创建新的table

5、不需要声明

6、table 的创建是通过"构造表达式"完成的,最简单的"构造表达式"——{}

a = {}
a[k] = 10
print(a[k])  -- 10

7、table 永远是"匿名的",一个持有 table 的变量与 table 自身之间没有固定的关联性

a = {}
a['x'] = 10
b = a  -- b 和 a 引用了同一个 table
print(b['x'])  -- 10
b['x'] = 20
print(a['x'])  --20
a = nil  -- 只有 b 还在引用 table
b = nil  -- 没有对 table 的引用了

当一个程序再没有对一个 table 的引用时,lua 的垃圾收集器最终会删除该 table,并复用它的内存

8、语法糖

a.x = 10 等价于 a['x'] = 10
a = {}
x = 'y'
a[x] = 10
print(a[x])  -- 10
print(a.x)  -- nil
print(a.y)  --10

9、若表示一个传统的数组或者线性表,只需以整数作为 key 来使用 table 即可

a = {}
for i = 1,10 do
    a[i] = io.read()
    end

10、长度

① 长度操作符"#"用于返回一个数组或者线性表的最后一个索引值(计算的是数组元素,不包括 hash 键值)

a = {}
for i = 1,10 do
    a[i] = io.read()  -- 1 2 3 4 5 6 7 8 9 10
    end
for i = 1,#a do
    io.write(a[i])  -- 1 2 3 4 5 6 7 8 9 10
    end
print(a[#a])  -- 10
a[#a+1] = 11  -- 将11添加到列表末尾
print(a[#a])  -- 11
print(a[#a+1])  -- nil

另外一种方法读取文件的前 10 行

a = {}
for i =1,10 do 
    a[#a+1] = io.read()
    end

② 未初始化的元素的索引结果都是 nil,Lua 将 nil 作为界定数组结尾的标志,处理含有"空隙"的数组,使用函数 table.maxn(),它将返回一个 table 的最大正索引数

a = {}
a[1000] = 1
print(#a)  -- 0
print(table.maxn(a))  -- 1000

③ table.getn()(同 #)

local tblTest2 =
{
    1,
    a = 2,  -- 记录
    3,
}
print(table.getn(tblTest2))  -- 1
  • 这个tblTest2不是一个简单的table,它混合了列表(list)和记录(record)两种风格,表中,a = 2是record风格。其次,record风格的record是不作为外表的长度计算。可以把它想象成一个函数,跟其他面向对象语言一样,函数是不记为内部变量的。
  • 既然像函数一样,那就可以输出a的值。print(tblTest2.a)就可以了。

    t= {
      [1]=4,
      [2]=5,
      [3]=6,
      [4]=7,
      [6]=8,
    }
    print("#" ,#t , "getn",table.getn(t) ,"maxn", table.maxn(t) )  -- 6 6 6
    print(t[5])`  -- nil
    t= {
      [1]=4,
      [2]=5,
      [3]=6,
      [5]=7,
      [6]=8,
    }
    print("#" ,#t , "getn",table.getn(t) ,"maxn", table.maxn(t) )  -- 3 3 6

    这里也太神奇了叭,真的搞不懂啊,哭了!

11、和全局变量一样,当 table 的某个元素没有初始化时,它的内容就为 nil,将 nil 赋予 table 的元素来删除该元素

但是!

local tblTest4 =
{
    1,
    nil,
}
print(table.getn(tblTest4))  -- 1
local tblTest5 =
{
    1,
    nil,
    2,
}
print(table.getn(tblTest5))  -- 3
local tblTest5 =
{
1,
nil,
2,
nil
}
print(table.getn(tblTest5))  -- 1

所以!

  • 在table中不要使用nil
  • 如果非要使用nil,必须用table.setn()函数去设置这个table表的长度。新版本的lua已经不支持setn了。
  • setn函数已过时,不要在lua的table中使用nil值,如果一个元素要删除,直接remove,不要用nil去代替。

12、key = '+1'、key = ‘01’ 和 key = ‘1’ 三者不同,当对索引的实际类型不是很确定时,可以明确地使用 tonumber()显示转换

1、boolean: false 和 true

2、lua 将值 false 和 nil 视为“假”,而其他值视为“真”

3、lua 在条件测试中,将 0 和 空字符串 也都视为”真“