Lua笔记

只写一开始不知道的

问题

Lua中函数和c语言一样要写在前面不然无法调用?

问题:闭包 迭代器  多状态和无状态迭代器  ipairs和pairs

Lua 调试(Debug)

require的加载原理

介绍

lua tolua

变量

Lua 中的变量全是全局变量,哪怕是语句块或是函数里,除非用 local 显式声明为局部变量,变量的默认值均为 nil。

多值赋值经常用来交换变量,或将函数调用返回给变量:

访问局部变量的速度比全局变量更快,同时局部变量可以避免命名冲突。

 

逻辑判断

lua中的Switch处理方案:

lua中没有Switch,可以手动来实现,摘自:https://www.cnblogs.com/FreeBirdLjj/p/3238621.html

循环

for循环: var从exp1变化到exp2,每次变化以exp3为步长递增var,并执行一次”执行体”。exp3是可选的,如果不指定,默认为1。for的三个表达式在循环开始前一次性求值,以后不再进行求值。

例子:

例子2:将f(n)函数写在下面会出错。

泛型 for 循环通过一个迭代器函数来遍历所有值,类似 java 中的 foreach 语句。格式:

i是数组索引值,v是对应索引的数组元素值。ipairs是Lua提供的一个迭代器函数,用来迭代数组。

repeat…until 循环的条件语句在当前循环结束后判断。

如果条件判断语句(condition)为 false,循环会重新开始执行,直到条件判断语句(condition)为 true 才会停止执行。

泛型 for 迭代器

迭代器 在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量。

迭代器提供了集合的 key/value 对,语法格式如下:

上面代码中,k, v为变量列表;pairs(t)为表达式列表。

泛型 for 的执行过程:

  • 首先,初始化,计算in后面表达式的值,表达式应该返回泛型 for 需要的三个值:迭代函数、状态常量、控制变量;与多值赋值一样,如果表达式返回的结果个数不足三个会自动用nil补足,多出部分会被忽略。
  • 第二,将状态常量和控制变量作为参数调用迭代函数(注意:对于for结构来说,状态常量没有用处,仅仅在初始化时获取他的值并传递给迭代函数)。
  • 第三,将迭代函数返回的值赋给变量列表。
  • 第四,如果返回的第一个值为nil循环结束,否则执行循环体。
  • 第五,回到第二步再次调用迭代函数

Lua使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素。包含以下两种类型:

  • 无状态的迭代器
  • 多状态的迭代器

ipairs和pairs的比较:

同:都是能遍历集合(表、数组)

异:ipairs 仅仅遍历值,按照索引升序遍历,索引中断停止遍历。不能返回 nil,只能返回数字 0,如果遇到 nil 则退出。只能遍历到集合中出现的第一个不是整数的 key。

pairs 能遍历集合的所有元素。即 pairs 可以遍历集合中所有的 key,并且除了迭代器本身以及遍历表本身还可以返回 nil。

例子:

 

字符串

字符串连接使用的是 ..

字符串操作:

函数 描述 示例 结果
len 计算字符串长度 string.len(“abcd”) 4
rep 返回字符串s的n个拷贝 string.rep(“abcd”,2) abcdabcd
lower 返回字符串全部字母大写 string.lower(“AbcD”) abcd
upper 返回字符串全部字母小写 string.upper(“AbcD”) ABCD
format 返回一个类似printf的格式化字符串 string.format(“the value is:%d”,4) the value is:4
sub returns substring from index i to j of s string.sub(“abcd”,2) bcd
string.sub(“abcd”,-2) cd
string.sub(“abcd”,2,-2) bc
string.sub(“abcd”,2,3) bc
find 在字符串中查找 string.find(“cdcdcdcd”,”ab”) nil
string.find(“cdcdcdcd”,”cd”) 2
string.find(“cdcdcdcd”,”cd”,7) 8
gsub 在字符串中替换 string.gsub(“abcdabcd”,”a”,”z”); zbcdzbcd 2
string.gsub(“aaaa”,”a”,”z”,3); zzza 3
byte 返回字符的整数形式 string.byte(“ABCD”,4) 68
char 将整型数字转成字符并连接 string.char(97,98,99,100) abcd

Lua 中的匹配模式直接用常规的字符串来描述。 用于模式匹配函数 string.find, string.gmatch, string.gsub, string.match。

可以使用模式串 ‘%d%d/%d%d/%d%d%d%d’ 搜索 dd/mm/yyyy 格式的日期:

尽管字符串和数字可以自动转换,但两者是不同的,像10 == “10”这样的比较永远都是错的。

如果需要显式将string转成数字可以使用函数tonumber(),如果string不是正确的数字该函数将返回nil。

两种写法:

print(tostring(10) == “10”) –> true
print(10 .. “” == “10”) –> true

Table

Lua 中的表(table)其实是一个”关联数组”(associative arrays),数组的索引可以是数字或者是字符串

table 不会固定长度大小,有新数据添加时 table 长度会自动增长,没初始的 table 都是 nil。

对 table 的索引使用方括号 [],默认初始索引一般以 1 开始。同时Lua 也提供了 . 操作,示例:

可以用任意类型的值来作数组的索引,但这个值不能是 nil。

Lua的垃圾回收机制会清理相对应的内存。

table不固定大小可以根据自己需要进行扩容。

Lua通过table来解决模块(module)、包(package)和对象(Object)。 例如string.format表示使用”format”来索引table string。

table最简单的构造函数是{},用来创建一个空表。可以直接初始化数组:

关于取table的长度

获取 table 的长度的时候无论是使用 # 还是 table.getn 都会在索引中断的地方停止计数,而导致无法正确取得 table 的长度。

可以使用以下方法来代替:

判断Table的长度

table.getn(table),使用#会出现一个问题,#取得长度是字符串的长度,也是字符串的字节数。

而table的长度被定义成一个整数下标 n 。 它满足 t[n] 不是 nil 而 t[n+1] 为 nil; 此外,如果 t[1] 为 nil ,n 就可能是零。

当table中存在nil值的时候,#可能会以当前nil值的下标记来确定table长度,这明显是有问题的。

并且table.getn(table)求长度时如果表中存在nil也会出现类似的问题,所以想避免长度问题的出现,就要避免table中出现nil值。使用remove来删除元素。

参考文章:http://www.cnblogs.com/youxin/p/3799339.html

如何判断table是否为空

if next(a) == nil then(存在一些问题,具体看https://blog.csdn.net/sunshine920103/article/details/54139274)

table 泛型元素去重, 只要元素支持 == 比较。

要写成完全的泛型,那么 v==a[i] 改成一个比较函数的指针 equal(v,a[i]):

元表

元表主要是用来实现面向对象,以及两个表之间的运算。具体可以看:lua元表和面向对象

函数

在 Lua 中,函数是被看作是”第一类值(First-Class Value)”,函数可以存在变量里。

Lua 编程语言函数定义格式如下:

Lua函数可以返回多个结果值

Lua 函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用三点 … 表示函数有可变的参数。

多返回值和可变长参数举例:

Image20180904185658.png

错误示范,函数没有返回值:

Image20180904191934.png

运算符

Lua的与或非分别为:and or not

lua中有^运算符,乘幂

从高到低的顺序:Lua中不存在 -=这种符号,不要再试了。自增也没有。

除了^和..外所有的二元运算符都是左连接的。

在 Lua 索引值是以 1 为起始。还可以以负数为数组索引值。

逻辑运算符认为false和nil是假(false),其他为真,0也是true。nil只和自己相等。

and和or的运算结果不是true和false,而是和它的两个操作数相关。例如:

  1. a and b — 如果a为false,则返回a,否则返回b
  2. a or b — 如果a为true,则返回a,否则返回b

如果想初始化一个表作为record使用可以这样:a = {x=0, y=0} <–> a = {}; a.x=0; a.y=0

模块

require是全局的,只要写过一次,整个项目都可以读到。

Lua 的模块是由变量、函数等已知元素组成的 table,创建一个模块就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 。格式如下:

可以像操作调用 table 里的元素那样来操作调用模块里的常量或函数。

上面的 func2 声明为程序块的局部变量,即表示一个私有函数,因此是不能从外部访问模块里的这个私有函数,必须通过模块里的公有函数来调用.

require函数用来加载模块 例如:

或者

执行 require 后会返回一个由模块常量或函数组成的 table,并且还会定义一个包含该 table 的全局变量

错误处理

我们可以使用两个函数:assert 和 error 来处理错误。实例如下:

执行以上程序会出现如下错误:

实例中assert首先检查第一个参数,若没问题,assert不做任何事情;否则,assert以第二个参数作为错误信息抛出。

error函数

语法格式:

功能:终止正在执行的函数,并返回message的内容作为错误信息(error函数永远都不会返回)

通常情况下,error会附加一些错误位置的信息到message头部。

Level参数指示获得错误的位置:

  • Level=1[默认]:为调用error位置(文件+行号)
  • Level=2:指出哪个调用error的函数的函数
  • Level=0:不添加错误位置信息

内存管理

Lua 实现了一个增量标记-扫描收集器。 使用两个数字来控制垃圾收集循环: 垃圾收集器间歇率和垃圾收集器步进倍率。 这两个数字都使用百分数为单位 (例如:值 100 在内部表示 1 )。

垃圾收集器间歇率控制着收集器需要在开启新的循环前要等待多久。 增大这个值会减少收集器的积极性。 当这个值比 100 小的时候,收集器在开启新的循环前不会有等待。 设置这个值为 200 就会让收集器等到总内存使用量达到 之前的两倍时才开始新的循环。

Lua 提供了以下函数collectgarbage ([opt [, arg]])用来控制自动内存管理:

  • collectgarbage(“collect”): 做一次完整的垃圾收集循环。通过参数 opt 它提供了一组不同的功能:
  • collectgarbage(“count”): 以 K 字节数为单位返回 Lua 使用的总内存数。 这个值有小数部分,所以只需要乘上 1024 就能得到 Lua 使用的准确字节数(除非溢出)。
  • collectgarbage(“restart”): 重启垃圾收集器的自动运行。
  • collectgarbage(“setpause”): 将 arg 设为收集器的 间歇率 (参见 §2.5)。 返回 间歇率 的前一个值。
  • collectgarbage(“setstepmul”): 返回 步进倍率 的前一个值。
  • collectgarbage(“step”): 单步运行垃圾收集器。 步长”大小”由 arg 控制。 传入 0 时,收集器步进(不可分割的)一步。 传入非 0 值, 收集器收集相当于 Lua 分配这些多(K 字节)内存的工作。 如果收集器结束一个循环将返回 true 。
  • collectgarbage(“stop”): 停止垃圾收集器的运行。 在调用重启前,收集器只会因显式的调用运行。

进程协程

在 Lua 里,最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西。

线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停。

面向对象

LUA中最基本的结构是table,所以需要用table来描述对象的属性

以下简单的类包含了三个属性: area, length 和 breadth,printArea方法用于打印计算结果:

创建对象

创建对象是为类的实例分配内存的过程。每个类都有属于自己的内存并共享公共数据。

访问属性

我们可以使用点号(.)来访问类的属性:

访问成员函数

我们可以使用冒号 : 来访问类的成员函数:

内存在对象初始化时分配

. 与 : 的区别在于使用 : 定义的函数隐含 self 参数,使用 : 调用函数会自动传入 table至 self 参数。

函数重写

可以重写基础类的函数,在派生类中定义自己的实现方式:

userdata

userdata可以将C数据存放在Lua变量中,userdata在Lua中除了赋值和相等比较外没有预定义的操作。userdata用来描述应用程序或者使用C实现的库创建的新类型。

常用标准库

Math库:

882218-20170331231939852-1795625827.jpg

注:

tmp1,tmp2 = math.modf(8/3)  分别是整数和小数部分

Lua和Unity的使用

 

 

 

 

 

 

 

Updated: 2019年1月26日 — 下午9:08

发表评论

电子邮件地址不会被公开。 必填项已用*标注