[Lua Study Notes] Getting Started with Lua

Insert image description here

(This is not a tutorial. It is recommended that people with basic programming knowledge read this article)

This article mainly contains some learning and understanding from the novice tutorial. Personally, I feel that Lua language and Python are similar in many ways.

Most of the following codes and tables are excerpted from novice tutorials

function start()

Lua variables

type of data

type of data describe
nil Only the value nil belongs to this class, which represents an invalid value (equivalent to false in a conditional expression) (similar to Null or None)
boolean false and true
number Double precision floating point number
string A string is represented by a pair of double quotes or single quotes
function Function written in C or Lua
userdata Represents any C data structure stored in a variable
thread Represents an independent line of execution, used to execute coroutines (then why do you call it a thread?)
table A table in Lua is actually an "associative array", and the index of the array can be a number, string, or table type. In Lua, table creation is accomplished through "constructive expressions". The simplest constructed expression is {}, which is used to create an empty table.

variable declaration

a = 5               -- 全局变量
local b = 5         -- 局部变量

In Lua, use local to explicitly declare the variable as a local variable, and anything that is not declared is a global variable.

a               -- nil
a = 5               -- number
a = false         -- bool
a = ""         -- string,单双引号都可以,支持转义字符,print出空字符串而非nil
在lua中字符串尾部没有\0,而且\0即使在字符串中也不代表结束且不计入长度
我们也可以用16进制来定义字符串
s = string.char(0x30,0x31)
n = string.byte(s,2)  --转为Ascii码,第一个字符是从1开始的而非0
print(s,n)     --结果: 01  49
a,b,c = 1,"a"         -- 多重赋值
print(a, b, c)         -- 1  a  nil
a = nil			 -- nil,回收变量
local multilineString = [[
This is a multiline string.
It can contain multiple lines of text.
No need for escape characters.
]]
print(multilineString)    -- 按格式输出括号内字符
This is a multiline string.
It can contain multiple lines of text.
No need for escape characters.

Regardless of whether an integer or a floating point type is defined, it is always a number in Lua. Variables that are not assigned a value are nil. Interestingly, even if an empty string is assigned, it is still of type string. It seems that nil in Lua should be similar to C, which means that the base address is not assigned.

Lua assigns values ​​to multiple variables at the same time and does not transfer variables, only transfer values:

a, b = 0, 1
a, b = a+1, a+1
print(a,b);               --> 1   1而非1	  2

By the way, you can also have a semicolon after the end of a Lua statement.

Other expressions

a = 0x11    -- 16进制表示,16+1=17
b = 2e10    -- 科学计数法,2*(10^10)
c = 5^2		-- 乘方,25
d = 5%2		-- 取余(mod),1
e = 5//2		-- 整除运算,2 (>=lua5.3)
f = 1<<3	-- 移位符号(>=lua5.3),二进制表示下移位:1 = 00000001左移三位(000)00001000 = 8
a,b = "abc","def"
c= a..b  --字符串连接,"abcdef"
print(#c) --#输出变量长度(可以是字符串或者表),6
-- 其他语法例如tostring(number),tonumber(string)都是很常规的
n = tonumber("a")   --nil,需要注意的是lua和cpp不同,单个字符也不会转为ASCII码

Lua syntax

judgment

Logical judgment (Lua is very special, this is more important)

Lua considers false and nil to be false, true and non-nil to be true, so 0 means it is also true.
The only thing to note is that inequality in Lua is ~=
and and or not respectively
. Let’s look at the following example:

a = nil -- false
b = 0  -- true
print(a and b)
print(a or b)
print(not a)

nil
0
true

It can be seen that conventional logical judgments in Lua will not return True or False. Only under the not judgment will True and False be returned, while and and or will only return the value of the variable corresponding to the logical value.

Let us give another example to understand better
(for example, a=nil, the value corresponds to false, so a and b return nil. And the value b=0 corresponds to True, a or b returns 0)

a = nil -- false
d = false -- false

B = 0   -- true
C = 1   -- true
and时一真一假输出结果是false的一方
print(a and C) --逻辑判断值返回了逻辑符号左右值中的对应真值和假值
print(C and d)
or时一真一假输出结果是true的一方
print(a or C)
print(C or d)

结果:
nil
false

1
1
上述例子是正常计算都可以得出的,现在让我们看几个特殊例子
以下例子请抛弃依次执行语句的程序思维,使用更逻辑化,更符合计算机的思维来判断
a = nil -- false
d = false -- false

B = 0   -- true
C = 1   -- true
and时两侧都是真值,则返回右侧的值
print(B and C)
print(C and B)
and时两侧都是假值,则返回左侧的值
print(a and d)
print(d and a)
结果:
1
0

nil
false

or时两侧都是真值,则返回左侧的值
print(B or C)
print(C or B)
or时两侧都是真值,则返回右侧的值
print(d or a)
print(a or d)

结果:
0
1

nil
false

Why is this? Perhaps from a programmatic perspective, we need to execute the statement and then make a judgment. But to implement a logic gate judgment, sometimes only a logic symbol and one of the values ​​are needed.

接下来用T代表真,F代表假,?代表任意bool
print(F and ?)
在进行and运算的时候,如果第一个值就为false,那输出值一定为false,?是什么都不影响了,所以结果一定为false,输出F即可
print(T and ?)
在进行and运算的时候,如果第一个值为true,我们依然无法确定输出值,此时我们需要知道?是true还是false
但是最后的运算结果一定是由?决定的,如果?为true运算就是true,问号为false运算就是false,所以and左值为真时,输出的结果一定是右值
因此该语句会输出 ?
print(T or ?)
同理,or运算中如果左值为true,结果一定为true,因此输出T即可
print(F or ?)
or运算中如果左值为false,最后结果则是由?是true还是false决定,因此输出结果一定是右值
上述语句输出 ? 

现在再回头看看刚才的例子,是不是能理解了?

Short circuit judgment

基于上述的原理我们可以进行短路判断
a = nil -- false
b = 0  -- true
print(b > 10 and "yes" or "no")

输出:
no

所以所谓短路判断,前面应当是正常的判断语句,最后加上and A or B,其中AB都是true值
【T and A or B = A, F and A or B =B】
当前面为真则输出A,当前面为假则输出B

if

if(0)
then
    print("0 为 true")
end

if else

a = 100;
if( a < 20 )
then
   print("a 小于 20" )
else
   print("a 大于 20" )
end
print("a 的值为 :", a)  --a 大于 20 
					    --a 的值为 :    100

cycle

while

The break keyword is universal

while( a < 20 )
do
   a = a+1
end

for

for i=1,10,2 do  --- 三个值依次代表起始,结束,步长,步长不输入默认为1
    print(i)
end 

repeat

a = 10
repeat  -- 不同与while for,repeat在循环结束时判断,类似do while
   print("a的值为:", a) --输出10,11,12,13,14,15
   a = a + 1
until( a > 15 ) --当a=16时退出

The most important knowledge point is that if, while, for, and function, don’t forget to add end.


Iterator

Generic for iterator

Iterators are similar to C#’s for each and python’s for in

array = {
    
    "Google", "Runoob"}

for key,value in ipairs(array)  -- key,value自定义常量名,ipairs(array)迭代列表
do
   print(key, value)
end

1  Google
2  Runoob

stateless iterator

function square(iteratorMaxCount,currentNumber)
   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
   return currentNumber, currentNumber*currentNumber
   end
end
--定义了一个方法square实现循环三次后结束

for i,n in square,3,0  --square,3,0代表了迭代方法和它的两个入参,当方法结束主动闭包
do
   print(i,n)
end

1    1
2    4
3    9

Multi-state iterator

If the iteration function needs to receive a lot of information, in order to simplify the input parameters of the iteration function, you might as well encapsulate all the status information into a table and use the table as the status constant of the iterator, because in this case all the information can be stored in the table , so iterative functions usually don't require a second parameter.

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

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

Google
Runoob

It should be noted that no matter what function is defined, the function needs to be returned to the iteration variable in order to finally output the corresponding value in the iterator.


Lua function

A few simple examples to get it right in one step

----------------------
function f()  --同样未用local声明,该函数为全局函数
	a,b=1,2   --  函数内定义没有local声明也是全局变量
	print(a,b)
end

f()		-- 1  2
--------------------
local function f(a,b,n)  --local声明后为局部函数
    c, d = a, b
    print(c, d,n)
end
f(1,2)		-- 1  2  nil
-------多返回值--------------------
function f(a,b,c)
	return a,b,c
end
local i,j =f(1,2)
print(i,j)		-- 1  2
--------可变参数---------------
function average(...)  --使用...可以接收任意多参数
   result = 0
   local arg={
    
    ...}    --> arg 为一个table,局部变量
   for i,v in ipairs(arg) do 
      result = result + v
   end
   print("总共传入 " .. #arg .. " 个数")
   print("总共传入 " .. select("#",...) .. " 个数")   --select("#",...)来获取可变参数的数量,和直接#arg功能是一样的
   return result/#arg
end

print("平均值为",average(10,5,3,4,5,6))
---总共传入 6 个数
---总共传入 6 个数
---平均值为    5.5
-----------
function average(a,...)  --也可以用固定参数+可变参数,但是固定参数一定放在可变参数之前
end
------------------------

select method

Usually when traversing variable-length parameters, you only need to use {...}. However, the variable-length parameters may contain some nil, so you can use the select function to access the variable-length parameters: select('#', ...) or select(n ,…)

select('#', …) returns the length of the variable parameter.
select(n, …) is used to return a list of all parameters starting from the starting point n to the end position.
When calling select, a fixed argument selector (selector switch) and a series of variable-length parameters must be passed in. If selector is a number n, then select returns a list of all parameters in the parameter list starting from index n to the end position, otherwise it can only be the string #, so select returns the total number of variable-length parameters.

function cal_sum(...)
    a,b =select(3,...)
    print(select(3, ...))
    print(select("#",...) )
end
cal_sum(1,2,3,nil,5,5)
print(a,b)

3	nil	5	5
6
3	nil

使用select赋值会对变量顺序赋值,而select本身可以获取序号及其后的所有可变参数

array

There is no single type of data structure in the traditional sense in Lua. There is only a table structure, which can store all the values ​​​​in it sequentially and provide an index for access.

It should be noted that the index starts from 1 instead of the traditional 0

function P ()
    return 1;
end
a={
    
    1,"ac",{
    
    },function() end,P}
print(a[3])
print(a[4])
print(a[5])
print(#a)
a[6] = 1223;
print(a[6])
print(#a)

结果:
table: 00BCA580
function: 00BCCAC8
function: 00BCCC48
5
1223
6

We found that the above table stores many strange values, including number, string, table and even two functions.

Through the output results, we find that for common variable types, table indexes can directly return values. For unconventional types such as table function, the storage type + storage address is returned.

-- insert用法,没有返回值
table.insert(a, "d") --插入到尾部
print(a[7])
s = table.insert(a, 2, 233) --插入到位置2,其后的元素都会后移一位
print(s)
print(a[2])

d
nil
233
-- remove会有返回值
s = table.remove(a, 1)
print(s)
print(a[1])

1
ac

character index

Tables can be indexed by characters:

a = {
    
    
    a = 1,
    b = "1234",
    c = function()
    end,
    d=123456,
    ["!?"] =123
}
a["abc"]="abc"
print(a["a"])
print(a.a)
print(a["!?"])   -- 这只是个例子,别用奇怪的符号命名
-- print(a.!?)   --打印不了的,符号会报错
print(a.abc)
print(a.def)    --没有这个下标

1
1
123
abc
nil

Insert image description here
Insert image description here

It is not difficult to find that the table is actually stored in the form of key-value pairs.


_G

_G is a global table, which stores all global variables. We can access any global variables through it

a = 1
b = 2
print(_G["a"])
print(_G.b)

1
2

If the above can still be understood, the following features are simply bizarre.

之前我们往tableA里不是使用table.insert插入了一个值吗?让我们看看怎么实现的

table.insert(table, 1, "aa") 
- lua内有一个全局变量,它的名字就叫table,它的类型是table
- 我们可以直接使用table.insert的原因其实是直接访问了这个名称为table的table的一个字符串索引
- 这个字符串索引的名称是"insert",这个索引对应的值是一个function
- 这个函数实现了往指定table的指定位置插入指定值的功能
print(table[1])
print(_G["table"]["insert"])

输出:
aa
function: 00CE8B48

Conclusion: Don’t forget

end

Guess you like

Origin blog.csdn.net/milu_ELK/article/details/131910189