[Lua语法]
1.Lua的特性
(1)可扩展性:Lua很容易和其他语言进行交互,很容易通过库扩展功能
(2)小巧,精简:Lua的库很小,易于学习,但是功能强大
(3)高效:Lua是目前平均执行效率最高的语言
(4)与平台无关:Lua几乎可以在任何平台上运行,原因是Lua完全使用ANSI C 编译器,而绝大多数系统只要有这个编译器,就可以在这个平台上运行
2.Lua语法特性
(1) Lua 中所有的值都可以作为条件。在控制结构的条件中除了 false 和 nil 为假,其他值都为真。所以 Lua 认为 0 和空串都是真。
(2)变量无需声明,未赋值过的变量都为nil
(3)函数是第一类值(和其他变量相同),意味着函数可以存储在变量中,可以作为函数的参数,也可以作为函数的返回值
(4)运算符比较:Lua 通过引用比较 tables、userdata、functions。也就是说当且仅当两者表示同一个对象时相等
(5)a ? b : c == (a and b) or c
(6)
2.Lua的表-Table
Lua中唯一的数据结构,可以实现数组,链表,队列,双端队列,功能异常的强大
内部实现细节:
(1)分为数组和哈希表两部分存储
3.函数和闭包
(1)闭包 =函数 + UpValue
(2)尾调用:当函数最后一个动作是调用另外一个函数时,我们称这种调用尾调用,尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用记录,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用记录,取代外层函数的调用记录就可以了。
尾递归:函数调用自身,称为递归。如果尾调用自身,就称为尾递归
4.Require函数
Lua中高级的加载库的函数,功能和doFile类似,但额外的不同点是:(1)Require会搜索目录加载文件,(2)Require会判断文件是否已经加载从而避免加载同一个文件多次。
Lua中有一张已存在的文件的表,记录已经加载的文件,通过将这个表Load[File] = nil,可以实现重新加载这个文件
5.字符串缓冲算法
在读取大量的字符串的时候,如果不是一次性读入,而是部分部分读入,那么不断地读入,合并字符串以及移动内存的开销及其的庞大。
汉诺塔问题
可以说大多数语言在处理字符串时都会有这个问题,C#中的StringBuilder,Java中的StringBuffer等都是对这种情况进行优化
6.元表和元方法
Lua中多态的实现机制,通过原表的_Index,如果表中没有这个元素,会访问_NewIndex元素
7.环境
全局环境_G, setFenv, 类似于命名空间中的概念,遍历全局环境中的表可以得到所有的全局变量和全局方法,设置合理的环境可以使我们各个模块的代码更加紧凑独立
8.Lua的面向对象
将b作为a的父类:在a中查找不到的方法和变量去b中查找, setmetatable(a, {__index = b})
多继承:_Index查找时的表是多个table,子类找不到的方法和变量就去父类表中遍历查找
成员的访问权限:将类中的方法和变量声明为local,外部访问时,访问返回的表,getBalance = (local)getBalance,而本地变量account不暴露给外部,从而实现account变量的私有化
Single-Method:
function newObject (value)
return function (action, v)
if action == "get" then return value
elseif action == "set" then value = v
else error("invalid action")
end
end
end
9.weak表
类似于C#中的weakReference,只是被弱引用的对象将被垃圾回收机制回收,也就是,可以引用这个对象,但却不影响这个对象被回收,
表的 weak 性由他的 metatable 的__mode 域来指定的,如果这个字符串中包含小写字母k那么这个表的key就是weakreference,包含v则v就是weakReference
10.Lua和C的调用
(1)使用栈来解决Lua和C中交互的两个问题
Lua中自动进行垃圾回收和内存管理,而C需要显式的执行内存分配和内存回收函数
Lua的动态类型和C中的静态类型不匹配
11.Lua字符串
表示一个字符串的核心就是字符串长度和指向存放字符串内存数据的指针,
(1)存放Lua字符串的变量存放的是对一份字符串的引用,因此字符串在Lua中是不可变的数据,改变一个字符串变量的数据并不会影响原来字符串的数据,这点和C#相同,也正是产生内存垃圾的地方之一,因此Lua必须要有一个全局的地方存储当前系统中的所有字符串,Lua使用一个散列桶来管理字符串
(2)这样设计的优点,使用散列值进行比较而不是字符串,提高了比较速度,相同字符串在内存中永远只存在一份,减少内存占用,当然这会在每次创建字符串的过程中多一次查找的过程,消耗并不大
(3)当数据非常多的时候需要重新散列,以降低每个桶上分配到的数据数量,也就是在哈希,重新计算哈希值然后重新将数据散列到不同的位置
12.Lua的内存管理和垃圾回收
(1)引用计数
为每个对象引用计数,为0则需要回收,但是缺点是不能解决循环引用的情况
(2)标记清除算法(Lua使用的)
每一次做GC的时候,首先扫描并且标记系统中的所有对象,被扫描并且标记的对象认为是可达的,这些对象不会被回收;反之没有被标记的对象认为是可以回收的
Lua5.0使用的双色标记清除算法:所有对象只有黑色和白色两种状态,缺陷在于每次做GC的时候所有对象的状态不能发生变化,也就是要一次性扫描并且清除所有对象,这可能会造成卡顿
Lua5.1以后使用改进的三色增量标记清除算法:
白色:一个对象在扫描结束后仍然是白色则说明该对象没有被系统中任何其他对象引用,可以回收其内存空间了
灰色:当前对象为待扫描状态,该对象已经被访问过,但是该对象引用的其他对象还没有被访问过
黑色:当前对象为已扫描状态,表示对象已经被GC访问过,并且该对象引用的其他对象也被访问过了
仍存在的问题:假如一个对象在GC过程中被创建则认为是白色而被回收
“”双白色”:将白色分为“当前白色”和“非当前白色”也就是用来区分是不是当前GC过程中产生的对象,而避免GC过程中产生额外的对象而被误回收