\

In the cone of light, all is fate

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

你可能想到,如果等号2边的数量不等会怎么样,左多右少,左边多到的相当于没赋值,但变量本身存在,值就为nil,反之,右边多的话,就白写呗。

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的。

posted @ 2021-11-24 13:59  Ymrt  阅读(127)  评论(0编辑  收藏  举报