Lua基础(一)
Lua的变量和JS有相似之处,都不需要声明类型,只是分为局部变量和全局变量:
a; --声明一个全局变量a
b = 0; --声明全局变量b并赋值为0
local c; --声明局部变量c
local d = nil; --声明局部变量d并赋值为nil
和JS一样,尽可能使用局部变量比较好,其中nil
可以理解为null
Lua可以对多个变量同时赋值,不会进行变量传递,仅做值传递:a,b = 1,2
如果你熟悉ES6的话,是不是觉得很眼熟,没错ES6的赋值解构和这差不多:[a,b] = [1,2]
不过这样是错的:a = b = 0
利用这个特性,可以很方便地交换变量的值:a,b = b,a
a,b,c = 1,2 -- a = 1; b = 2; c = nil;
a,b = 1,2,3 -- a = 1; b = 2;
函数
function foo(param1,param2)
return param1,param2;
end
Lua中的函数、循环、判断都是没有大括号的,可能是因为需要表强大的同时语言本身的体积足够小,但总得有个符号来表示函数已经结束,end
是表示结束的标志;另外Lua的函数可以返回多个值,上面的例子中返回了两个,返回出去是2个以,
隔开的的值:a,b = foo(1,2)
。
当我们不知道一个函数该接受多少参数时,用...
表示,如果知道几个固定的参数,其他参数不知道的话,就把固定参数写在前面:
function foo(...)
function fun(a,b,...)
运算符
其实所有语言运算符都是一样的,只是写法不同,只列出几个明显区别于其他语言的:
and -- 与
or -- 或
not -- 非
~= -- 不等
.. -- 连接两个字符串
# -- 返回字符串或表的长度
--注意^和..都是右连接
x^y^z -- 其实是 x^(y^z) ,只不过不知道这点也不会出错
迭代器
--while循环
while(true)
do
print("你猜我会循环多久")
end
--repeat...until,其实就是do...while()
repeat
print("...")
until(condition)
--for
for i=1,10,1 do
print(i)
end
--for,条件也可以用函数返回值,并且第三个条不写则默认为1
function f(x)
return x*2
end
for i = 1,f(5) do
print(i)
end
--for,泛型for,其实就是foreach
list = {"a","b","c"}
for i,val in ipairs(list) do
print(val)
end
--ipairs是Lua提供的一个迭代器函数,用来迭代数组,后面会讲到自定义的迭代函数,所以知道为什么lua体积小了吧,很多地方都只准备了个框架,用的时候要自己填充
ipairs
函数会返回3个值,这个3值即for
中的条件,在上面的代码中可以看到Lua中for的3个条件是逗号隔开,而函数返回多个值也是,这正好是变量中讲到的多值赋值。正常情况下,使用Lua提供的ipairs
肯定够用了,但我们最好还是知道一下,它做了什么,我们先举一个其他例子:
for i,val in square,3,0
do
print(i,val)
end
--有以上的循环,3和0可以看作是square的参数,你说为什么不用 square(3,0),因为泛型 for 在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量 = square,3,0。
--虽然3,0最后是作为square的参数,但square不是现在执行,而是把square,3,0交给for in去处理
--square函数返回的是某数的平方:
function square(MaxCount,Value)
if Value<MaxCount
then
Value = Value+1
return Value, Value*Value
end
end
--结果
1 1
2 4
3 9
所以ipairs
就是返回了“迭代函数、状态常量、控制变量”,即square,3,0
function iter (a, i)
i = i + 1
local v = a[i]
if v then
return i, v
end
end
function ipairs (a)
return iter, a, 0
end
你应该会注意到ipairs
的返回值中有一个固定值0,阅读代码后我们知道这个0是索引的起点,但在iter
函数中这个索引在一开始就加了1,恭喜你发现了Lua又一个与众不同的地方,它的索引是从1开始的,当然我们也可以将索引设为0,设为负数也行,到后讲到表的时候你就明白了。
上面的迭代器叫做无状态迭代器,可能你还不理解无状态是指什么,没关系,先记着这个名字,我们去了解一下什么是多状态迭代器。
先看一下这个for in
,和之前的有什么不一样:
for element in elementIterator(array)
do
print(element)
end
是不是发现element
这个地方和之前不一样,之前这里是2个参数,现在只有1个,但这样明显看上去更舒服,也更熟悉,那么发生了什么?
首先我们知道,这个element是数组array中的项,也就是说索引没有了,也就意味着elementIterator
只返回了项,那么为什么之前的无状态迭代器是返回索引的?仔细回想无状态迭代器的代码,我们就能明白,索引i
在每次循环后都会被迭代函数的返回更新值,然后下一次循环就会从i来获取新的值作为索引起点,如果还是想象不出来,我们先看一下elementIterator
这个函数的内容:
array = {"Google", "Runoob"}
function elementIterator (collection)
local index = 0
local count = #collection
-- 闭包函数
return function ()
index = index + 1
if index <= count
then
-- 返回迭代器的当前元素
return collection[index]
end
end
end
看到闭包,你想到什么?是不是想到闭包的特点,里面的index不会被释放,会一直保留。也就是说索引虽然在表面消失了,但仍然在迭代函数中发挥作用,这种写法可以让for in
看上去更加简洁,代价是多花费一点内存,这种将索引等状态保存在迭代函数内的,叫多状态迭代器。
If
if(bool)
then
...
elseif(true)
then
...
else
...
end
If很简单,就是这语法我也是醉了,另外要注意,Lua中0也代表true,而nil是可以代表false的。