最近开始学习cocos2d,也随便学习一下lua语言的简单使用。一些基本的不同:
交互模式使用lua语言:
lua/luajit$ ./LuaJIT-2.0.1/src/luajit -i
LuaJIT 2.0.1 -- Copyright (C) 2005-2013 Mike Pall. http://luajit.org/
JIT: ON CMOV SSE2 SSE3 SSE4.1 fold cse dce fwd dse narrow loop abc sink fuse
> a={'abc', 'def'}
> print(a[1])
abc
> print(a[0])
nil
lua里一切都是表,即{},对应到底层就是hash表。点就是访问表中元素,不限类型, 冒号是访问表中函数,且表自身作为参数列表的第一个参数。对应到面向对象编程,点可以简单理解为静态成员函数,冒号可以简单理解为类成员函数。
> a = {}
> function a:output(...) print(self, ...) end
> a:output(1,2,3)
table: 0x40d45bd8 1 2 3
> a.output(a, 1,2,3)
table: 0x40d45bd8 1 2 3
> a.output(self, 1,2,3)
nil 1 2 3
上面的output被以两种方法访问了。注意,保留字self只有在函数定义时才有用。
在quick cocos2d中,有这么个函数:
function handler(target, method)
return function(...)
return method(target, ...)
end
end
这样在类中给一个变量赋一个成员函数时,可以写成:
local onTouch = handler(self, self.doTouch)
其实跟
local onTouch = self:doTouch
一个意思,但是感觉前者更顺眼一些。
由于懂点python,又懂点javascript和css,所以定义一个表都时常写错。当然也跟lua里诡异风格相关。
a = {
name = 'wangyang',
age = 129
}
或者
a = {
['name'] = 'wangyang',
['age'] = 129
}
别的语言里都是标准json格式,lua有点不伦不类。第二种写法完全是为了方便变量名以非字符和下划线打头设计,但加引号也就够了, 为嘛还要加中括号,表示费解,估计是为了加快解析,跟数组定义绝对区分开来:
a = {
'name',
'age'
}
当然访问的时候,也有两方法,a.name
和a['name']
。
Lua就是这么简洁,连continue都省略掉了,但据说lua 5.2版本里加入了goto保留字来解决continue缺失的问题。 当然其实没有continue也不是什么大的问题,加一层if条件判断就行了,当然会导致代码缩进更深一层。
还一点很不一样,就是return只能是一个代码块的最后一句。比如:
function output()
return
print('hello world')
end
只能写成:
function output()
do return end
print('hello world')
end
真假判断非常明确:在if while等判断语句中,只有false和nil是假,其他都是真,包括空串和数字0
相等判断非常明确:table, userdata, functions三种类型只有是同一个内存地址时才相等,相当于其他语言里的===
如下代码:
local baba = {}
if baba == {} then
print('equal')
else
print('not equal')
end
会输出not equal
。
再如代码:
a = {}; a.x = 1; a.y = 0
b = {}; b.x = 1; b.y = 0
c = a
其结果是a~=b
,但a==c
。
lua的for循环语句有很多坑爹之处。例如:
for i=1,f(x) do print(i) end
i尽管没有local修饰,但是局部变量,只在循环里可见,如果循环外需要i的值,那么就在循环外定义一个变量,然后在循环中将i值赋给该变量。
f(x)只会被调用一次,循环次数在循环开始前就已经确定了,不会再改变,例如:
> s={"a", "b", "c", "d"}
> for i = 1, #s do print(i, s[i]) if i == 3 then table.remove(s, 3) end end
1 a
2 b
3 c
4 nil
在循环内i能改变,但不会影响到循环的次数。如下面的代码只会运行10次:
for i = 1,10 do
i = i -1
print(i)
end
for循环中有一个do,其实do和end才是配对的,比较容易写掉。循环范围中1,10
,是[1,10]
,即闭区间。循环还可以控制递增值,逆序循环如:
for i=10,1,-1 do print(i) end
由于有以上很多注意点,一个完备的删除函数应该这么写:
function table.removeItem(list, item, removeAll)
local rmCount = 0
for i = 1, #list do
if list[i - rmCount] == item then
table.remove(list, i - rmCount)
if removeAll then
rmCount = rmCount + 1
else
break
end
end
end
end
for循环还有如下形式,跟python里的for in语法有点像:
for i,v in ipairs(a) do print(v) end
for k in pairs(t) do print(k) end
上面写法跟如下代码等效:
table.foreachi(a, print)
table.foreach(t, function(k,v) print(k) end)
-- 预加载列表
package.preload
-- 加载器,可以定制查找lua模块的方式
package.loaders
-- 已经加载列表,置nil即可卸载已加载模块
package.loaded
-- lua文件查找路径,例如:./?.lua;/usr/lib/?.lua;xxx/?.lua
package.path
-- c模块查找路径
package.cpath
package.seeall
-- 加载c模块
package.loadlib()
功能:是垃圾收集器的通用接口,用于操作垃圾收集器
参数:
opt:操作方法标志
"Stop": 停止垃圾收集器
"Restart": 重启垃圾收集器
"Collect": 执行一次全垃圾收集循环
"Count": 返回当前Lua中使用的内存量(以KB为单位)
"Step": 单步执行一个垃圾收集. 步长 "Size" 由参数arg指定(大型的值需要多步才能完成),如果要准确指定步长,需要多次实验以达最优效果。如果步长完成一次收集循环,将返回True
"Setpause": 设置arg/100的值作为暂定收集的时长
"Setstepmul": 设置arg/100的值,作为步长的增幅(即新步长=旧步长*arg/100)
功能:打开并且执行一个lua块,当忽略参数filename时,将执行标准输入设备(stdin)的内容。返回所有块的返回值。当发生错误时,dofile将错误反射给调用者.
dofile不能在保护模式下运行
功能:终止正在执行的函数,并返回message的内容作为错误信息(error函数永远都不会返回)
通常情况下,error会附加一些错误位置的信息到message头部.
Level参数指示获得错误的位置
Level=1[默认]:为调用error位置(文件+行号)
Level=2:指出哪个调用error的函数的函数
Level=0:不添加错误位置信息
功能:记录全局环境的变量值的表_G._G = _G
功能:返回函数f的当前环境表
参数:f可以为函数或调用栈的级别,级别1[默认]为当前的函数,级别0或其它值将返回全局环境_G
功能:返回指定对象的元表(若object的元表.__metatable项有值,则返回object的元表.__metatable的值),当object没有元表时将返回nil
功能:返回三个值 迭代函数、表、0
多用于穷举表的键名和键值对
如:
for i,v in ipairs(t) do
...
end
每次循环将索引赋级i,键值赋给v
注:本函数只能用于以数字索引访问的表 如:t={"1","cash"}
功能:装载一个块中的函数,每次调用func将返回一个连接前一结的字串,在块结尾处将返回nil
当没有发生错误时,将返回一个编译完成的块作为函数,否则返回nil加上错误信息,此函数的环境为全局环境
chunkname用于错误和调试信息
功能:与load类似,但装载的是文件或当没有指定filename时装载标准输入(stdin)的内容
功能:与load类似,但装载的内容是一个字串
如:assert(loadstring(s))()
功能:允许程序遍历表中的每一个字段,返回下一索引和该索引的值。
参数: table:要遍历的表
index:要返回的索引的前一索中的号,当index为nil[]时,将返回第一个索引的值,当索引号为最后一个索引或表为空时将返回nil
注:可以用next(t)来检测表是否为空(此函数只能用于以数字索引的表与ipairs相类似)
功能:返回三个值 next函数、表、0
多用于穷举表的键名和键值对
如:
for n,v in pairs(t) do
...
end
每次循环将索引赋级i,键值赋给v
注:本函数只能用于以键名索引访问的表 如:t={id="1",name="cash"}
功能:在保护模式下调用函数(即发生的错误将不会反射给调用者)
当调用函数成功能返回true,失败时将返回false加错误信息
功能:简单的以tostring方式格式化输出参数的内容
功能:检测v1是否等于v2,此函数不会调用任何元表的方法
功能:获取表中指定索引的值,此函数不会调用任何元表的方法,成功返回相应的值,当索引不存在时返回nil
注:本函数只能用于以数字索引访问的表 如:t={"1","cash"}
功能:设置表中指定索引的值,此函数不会调用任何元表的方法,此函数将返回table
功能:当index为数字将返回所有index大于index的参数:如:select(2,"a","b") 返回"b"
当index为"#",则返回参数的总个数(不包括index)
功能:设置函数f的环境表为table
参数:f可以为函数或调用栈的级别,级别1[默认]为当前的函数,级别0将设置当前线程的环境表
功能:为指定的table设置元表metatable,如果metatable为nil则取消table的元表,当metatable有__metatable字段时,将触发错误
注:只能为LUA_TTABLE 表类型指定元表
功能:尝试将参数e转换为数字,当不能转换时返回nil
base(2~36)指出参数e当前使用的进制,默认为10进制,如tonumber(11,2)=3
功能:将参数e转换为字符串,此函数将会触发元表的__tostring事件
功能:返回参数的类型名("nil","number", "string", "boolean", "table", "function", "thread", "userdata")
功能:返回指定表的索引的值,i为起始索引,j为结束索引
注:本函数只能用于以数字索引访问的表,否则只会返回nil 如:t={"1","cash"}
功能:与pcall类似,在保护模式下调用函数(即发生的错误将不会反射给调用者)
但可指定一个新的错误处理函数句柄
当调用函数成功能返回true,失败时将返回false加err返回的结果