Lua基础(一)(Lua Foundation (I))

变量

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中的函数、循环、判断都是没有大括号的,可能是因为需要表强大的同时语言本身的体积足够小,但总得有个符号来表示函数已经结束,是表示结束的标志;另外Lua的函数可以返回多个值,上面的例子中返回了两个,返回出去是2个以隔开的的值:。

end
,
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体积小了吧,很多地方都只准备了个框架,用的时候要自己填充

函数会返回3个值,这个3值即中的条件,在上面的代码中可以看到Lua中for的3个条件是逗号隔开,而函数返回多个值也是,这正好是变量中讲到的多值赋值。正常情况下,使用Lua提供的肯定够用了,但我们最好还是知道一下,它做了什么,我们先举一个其他例子:

ipairs
for
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

你应该会注意到的返回值中有一个固定值0,阅读代码后我们知道这个0是索引的起点,但在函数中这个索引在一开始就加了1,恭喜你发现了Lua又一个与众不同的地方,它的索引是从1开始的,当然我们也可以将索引设为0,设为负数也行,到后讲到表的时候你就明白了。

ipairs
iter

上面的迭代器叫做无状态迭代器,可能你还不理解无状态是指什么,没关系,先记着这个名字,我们去了解一下什么是多状态迭代器。

先看一下这个,和之前的有什么不一样:

for in
for element in elementIterator(array)
do
   print(element)
end

是不是发现这个地方和之前不一样,之前这里是2个参数,现在只有1个,但这样明显看上去更舒服,也更熟悉,那么发生了什么?

element

首先我们知道,这个element是数组array中的项,也就是说索引没有了,也就意味着只返回了项,那么为什么之前的无状态迭代器是返回索引的?仔细回想无状态迭代器的代码,我们就能明白,索引在每次循环后都会被迭代函数的返回更新值,然后下一次循环就会从i来获取新的值作为索引起点,如果还是想象不出来,我们先看一下这个函数的内容:

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

————————

variable

Lua’s variables are similar to JS. They do not need to declare types, but are divided into local variables and global variables:

a;  --声明一个全局变量a
b = 0;  --声明全局变量b并赋值为0
local c;    --声明局部变量c
local d = nil;  --声明局部变量d并赋值为nil

Like JS, it is better to use local variables as much as possible, which can be understood as

nil
null

Lua can assign values to multiple variables at the same time without variable transfer, but only value transfer:

a,b = 1,2

If you are familiar with ES6, do you think you are familiar with it? Yes, the assignment and Deconstruction of ES6 is similar to this:

[a,b] = [1,2]

But this is wrong:

a = b = 0

With this feature, you can easily exchange the values of variables:

a,b = b,a

You may think what happens if the number of sides of the equal sign 2 is different. More on the left and less on the right. The more on the left is equivalent to no assignment, but the variable itself exists, and the value is nil. On the contrary, if there are more on the right, it is written in vain.

a,b,c = 1,2 --  a = 1; b = 2; c = nil;
a,b = 1,2,3 --  a = 1; b = 2;

function

function foo(param1,param2)
    return param1,param2;
end

Functions, loops and judgments in Lua do not have curly braces, which may be because the table needs to be powerful and the volume of the language itself is small enough, but there must be a symbol to indicate that the function has ended, which is a sign to indicate the end; In addition, Lua’s function can return multiple values. In the above example, it returns two values separated by:.

end
,
a,b = foo(1,2)

When we don’t know how many parameters a function should accept, it means that if we know several fixed parameters and don’t know other parameters, we will write the fixed parameters in the front:

...
function foo(...)
function fun(a,b,...)

operator

In fact, all language operators are the same, but they are written differently. Only a few are listed that are obviously different from other languages:

and -- 与
or  -- 或
not -- 非
~=  -- 不等
..  -- 连接两个字符串
#   -- 返回字符串或表的长度

--注意^和..都是右连接
x^y^z   -- 其实是 x^(y^z) ,只不过不知道这点也不会出错

iterator

--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体积小了吧,很多地方都只准备了个框架,用的时候要自己填充

The function will return three values, which are the conditions in. In the above code, you can see that the three conditions for in Lua are separated by commas, and the function returns multiple values, which is exactly the multi value assignment mentioned in the variable. Under normal circumstances, it must be enough to use what Lua provides, but we’d better know what it does. Let’s give another example first:

ipairs
for
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

Therefore, it returns “iterative function, state constant and control variable”, that is

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

You should notice that there is a fixed value 0 in the return value. After reading the code, we know that this 0 is the starting point of the index, but in the function, the index is added with 1 at the beginning. Congratulations on finding another difference in Lua. Its index starts from 1. However, we can also set the index to 0 or negative, You’ll understand when you talk about the watch later.

ipairs
iter

The iterator above is called stateless iterator. Maybe you don’t understand what stateless means. It doesn’t matter. Remember the name first. Let’s learn what a multi state iterator is.

Take a look at this first. What’s different from the previous one:

for in
for element in elementIterator(array)
do
   print(element)
end

Did you find that this place is different from before. There were two parameters here before, but now there is only one, but it obviously looks more comfortable and familiar. So what happened?

element

First of all, we know that this element is an item in the array, that is, there is no index, which means that only items are returned. So why did the previous stateless iterator return the index? If we carefully recall the code of the stateless iterator, we can understand that the index will be updated by the return value of the iterative function after each cycle, and then the next cycle will obtain a new value from I as the index starting point. If we still can’t imagine it, let’s take a look at the content of this function first:

elementIterator
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

What do you think of when you see the closure? Do you think of the characteristics of closures? The index inside will not be released and will be retained all the time. In other words, although the index disappears on the surface, it still plays a role in the iterative function. This writing method can make it look more concise at the cost of spending a little more memory. This method of saving the index and other states in the iterative function is called multi state iterator.

for in

If

if(bool)
then
	...
elseif(true)
then
	...
else
	...
end

If is very simple. I’m drunk with this syntax. In addition, note that 0 in Lua also represents true, while nil can represent false.