lua学习笔记

lua特性总结:

  1. lua可以多重赋值,同时函数可以有多个返回值
  2. lua函数是一种first-class value
  3. lua函数可以嵌套,closure的概念
  4. 元表、元方法
  • 注释
--:行注释
--[[  ]]: 块注释
小技巧:
注释代码:
--[[  
代码
--]]
重新启用这段代码:
---[[  
代码
--]]
  • 全局变量:将一个值赋予一个全局变量就创建了该全局变量(访问一个未创建的全局变量得到的值为nil);删除一个全局变量,只需将其赋值为nil
  • 基础类型
1.nil(空):
用于区别其它任何值;
可用于表示一种“无效值”的情况;
2.boolean(布尔):
false和true;
Lua将值false和nil视为“假”,其它视为真;
3.number(数字):
用来表示实数;
合法的表示方法:4、0.4、4.57e-3;
4.string(字符串):
字面字符串以一对匹配的单引号或双引号来界定;
lua提供了字符串和数字的自动转换;
手动转换:
字符串转数字:tonumber();
数字转字符串:tostring();或者将该数字与一个空字符串相连接(number .. "")(..是字符串连接操作符);
#:长度操作符,放在字符串的前面,用于获取字符串的长度;
5.table(表):
最简单的构造表达式:a = {}; 
table永远是匿名的,只能通过引用来持有table,当一个table的引用计数为0时,lua的垃圾收集器会删除该table;
table可以用不同类型的索引来访问value;
a.x:等同于a["x"];
a[x]:等同与a[变量x的值];
数组通常以1做为索引的起始值;
#:返回数组或线性表的最后一个索引值,以nil作为界定数组结尾的标志;
table.maxn:返回一个table的最大正索引数;
6.function(函数):
7.userdata(自定义类型):
8.thread(线程):
  • table构造式:
列表风格:a = {"Sunday", "Monday",},索引默认从1开始(print(a[1]) = "Sunday"),不能使用负数的索引;
记录风格:a = {x="Sunday", y="Monday"},等价于{["x"]="Sunday", ["y"]="Monday"};
两种风格混合(中间用;隔开):a = {"Sunday", "Monday"; x="Sunday", y="Monday"};
  • 多重赋值:
特性:首先匹配左右两边的赋值对象(丢掉多余的、用nil补充不足的);然后同时进行赋值操作(没有前后顺序之分)。
1.用于交换变量的值:a, b = b, a;
2.用于函数返回多个值
  • 控制结构
1.if then  + end
2.if then elseif then else + end
3.while  do + end
4.repeat  until(相当于C++里面的do while)
5.数字型for:
for var=exp1, exp2, exp3 do
end
var从exp1变化到exp2,每次变化的步长为exp3,缺省为1,如果不想设置上限的话,可以使用常量math.huge;

6.泛型for:
for <var-list> in <exp-list> do
    <body>
end
通常exp-list只有一个元素,即一句对迭代器工厂的调用;
如:for k, v in pairs(t) do print(k, v) end;
var-list第一元素称为控制变量,当它为nil时,循环结束;
for做的第一件事情是对exp-list求值,for会保存三个值:迭代器函数、恒定状态、控制变量初值;
在初始化步骤之后,for会以恒定状态和控制变量来调用迭代器函数,然后for将迭代器函数的返回值赋予变量列表中的变量。如果第一个返回值为nil,那么循环终止。否则,执行循环体,并重复这个过程。
for var_1, ..., var_n in <exp-list> do <block> end
等价于:
do
  local _f, _s, _var = <explist>
  while true do
    local var_1, ..., var_n = _f(_s, _var)
    _var = var_1
    if _var==nil then break end
    <block>
  end
end
  • 变长参数:
function add(...)
  local s = 0
  for i, v  in ipairs{...} do
    s = s+v
  end
  return s
end

print(add(3, 4, 10, 25, 12))

参数中的...表示函数可接受不同数量的参数;
函数要访问它的参数时,需要通过...来获得;
如果变长参数中包含nil,则需要用函数select来访问变长参数;
调用select时,必须传入一个selector和变长参数列表。如果selector为数字n,则返回它的第n个可变实参;如果selector为字符串“#”,则返回变长参数的总数(包含nil);
for i=1, select("#", ...) do
  local arg = select(i, ...)  -- 得到第i个参数
  <body>
end
  • 具名参数:把函数形参列表放入到一个table中,调用函数时传入实参table
  • 函数是一种第一类值(first-class value):表示lua中的函数与其它传统类型具有相同的地位。可以存储到变量或table中,可以作为实参传递给函数,可以作为函数的返回值
  • 词法域(lexical scoping):一个函数可以嵌套到另一个函数中,内部的函数可以访问外部函数中的局部变量(external local value / upvalue)
  • 闭包函数(closure):是指一个函数及一系列这个函数会访问到的upvalue。因此,若一个closure没有访问到upvalue,那它就是一个传统意义上的函数
  • 元表、元方法:
元表是元方法的集合,设置方法setmetatable(tablename, metatable);
元方法是自定义的操作集合,相当于C++中的操作符重载;
算术类的元方法:
+: __add
-:  __sub
*: __mul
/:  __div
-:  __unm(相反数)
%:__mod
^: __pow

关系类的元方法:
==:__eq
<:    __lt
<=:  __le

库定义的元方法:
print():__tostring
__metatable:用于保护集合的元表,使用户既不能看也不能修改集合的元表

__index元方法:
用于集合的查询,当访问table中不存在的字段时,解释器就会去查找一个叫__index的元方法;

__newindex元方法:
用于集合的更新,当更新table中不存在的字段时,解释器就会去查找一个叫__newindex的元方法;

具有默认值的table:
v1:
function setDefault(t, d)
    local mt = {__index = function() return d end}
    setmetatable(t, mt)
end

v2:
key = {}
local mt = {__index = function(t) return t[key] end}
function setDefault(t, d)
    t[key] = d
    setmetatable(t, mt)
end
相关链接: