一, 概述

  1. lua作为一种脚本语言,安装轻便,常用于嵌入应用程序中,为应用程序提供灵活的扩展和定制的功能。底层是使用c语言进行开发的

二,安装

  1. 下载安装包:http://www.lua.org/ftp/lua-5.3.0.tar.gz
  2. copy安装包到Linux系统,tar zxvf lua-5.3.0.tar.gz
  3. make linux test
  4. 如果对客户端的安装目录有要求的话,可以修改makefile中的install_top为自己想要安装的目录(这里最好是修改成绝对目录,因为如果是相对目录的话,cd之后相对目录就会有问题)
  5. make install,执行makefile
  6. 安装完成,客户端地址:install_top/usr/local/bin/lua

三,执行方式

  1. 在客户端直接执行
./lua

lua 版本 变化 lua语言下载_迭代

  1. 编写脚本,执行lua 脚本

lua 脚本名称

  1. 编写lua脚本,脚本中第一行标明 “#!install_top/usr/local/bin//lua”;修改脚本为可执行态,chmod+x 脚本;./脚本 即可执行
  1. vi test.lua test.lua 内容:
1.  #!./lua
 print(“hello ,my first lua print”)
  1. 修改脚本为可执行态
1.  chmod +x test.lua
  1. 执行脚本
3.  ./test.lua
 hello ,my first lua print

lua 版本 变化 lua语言下载_后端_02

四, 基本语法

  1. 支持的数据类型:
- nil:空数据类型;变量无效值;变量默认值
  - number:双精度类型的小数,在lua中只有这一种小数类型
  - string:字符串类型
  - boolean:布尔类型(true/false)
  - function:函数
  - table:字典和list都用table来表示
  1. 变量

1)变量声明

a=123   -- 全局变量:默认的变量的声明是全局变量,在整个文件范围内生效

	do
 		local a=123  -- 局部变量,使用local关键字声明的变量是局部变量,只在声明局部变量的语句块(end关键字的出现标识一个语句块的结束)内生效
 		print(a)	-- 123
 	end
 	print(a)   -- nil

-- 	表中的域:在table中声明的变量,那么只在table中生效

2)变量赋值

variable=123		--  单个变量赋值 
-- 多个变量赋值
a,b,c=1,2,3,这种多个变量同时进行赋值的方式,如果变量的个数大于值的个数,那么从左往右,多余的变量会被赋值成nil。如果是变量的个数小于值的个数,那么多余的值会被忽略掉

a,b,c=1,2
print(a,b,c)     --  1	2	nil
a,b=4,5,6
print(a,b,c)	--   4	5	nil
  1. 流程控制
--  循环语句:while(true) do .... end
i=0
while(i<3) 
do 
	print(i)    -- 0   1   2
	i=i+1
end

--  for语句数值循环:for var=expr1,expr2,expr3 do ... end   ==>(var:初始变量名,expr1:变量初始值,expr2:变量迭代结束值,expr3:变量迭代表达式【可选,默认是+1】)

for i=1,7,i+2 do
	print(i)	-- 1	6
end

-- for语句泛型循环:for k,v in ipairs(xxx) do ... end ==>(ipairs只会遍历key是数值的元素);for k,v in pairs(xxx) do ... end ==>(pairs会遍历所有的key)

tb={'a', 'b', 'c'}
tb['k']='d'
tb[5]='hh'
for k,v in ipairs(tb) do
	print(k,v)
end
output:
1	a
2	b
3	c

for k,v in pairs(tb) do
	print(k,v)
end

ouput:
1	a
2	b
3	c
k	d
5	hh


-- repeat ... until(condition)

i=0
repeat
	print('----------',i)
	i=i+1
until(i==3)

ouput:
----------	0
----------	1
----------	2

-- break关键字
i=0
repeat
	print('----------',i)
	i=i+1
	if (i>1) then break end 
until(i==3)


ouput:
----------	0
----------	1

-- goto关键字
-- 声明一个label
:: mylabel :: print('this is a label')
print('==================')
-- 跳到指定的label处
goto mylabel 

-- 注意:上面的代码会一直循环的print,所以在使用goto的时候需要时在指定的条件下才可以执行

i=0
:: mylabel :: do
	print('this is a label')
end
i=i+1
if(i<3) then
	goto mylabel
end

output:
hello ,my first lua print
this is a label
this is a label
this is a label

-- if判断语句
if() then ''''
else ''''
end
  1. 函数

函数的定义:

[local] function myFun(variables)
		xxx
		return 
	end
	function: 定义函数的关键字
	local:标识定义的函数是局部函数,只在当前局部生效。默认情况下不加local标识是全局函数,全局都有效使用
	myFun:自定义的函数名称
	variables:函数所需的形参,可以传n>=0个参数。这里的参数可以是任意基本类型,或者是函数
	return:如果函数有返回值,用return来进行标识
	end:函数定义的结束

函数的用法:

1. 根据函数的使用范围通过myFun(vs)来进行调用
	2. 形参和实参:形参指的是我们在定义函数的时候指定参数列表;实参指的是我们在实际执行函数的时候所传的参数;
			在lua中,形参和实参的个数是可以不一致的,多者忽略,少者补nil的原则
----------------------------------------
-- 函数定义
local function my(a,b)
	print(a,b)
end
----------------------------------------
-- 形参多于实参的例子
my(1) 

output:
1	nil

-- 形参少于实参的例子
my(1,2,3)

output:
1	2
----------------------------------------
-- 把函数当做参数传递
local function f1(a)
	print('this is f1')
	print(a)
end

local function f2(f)
	f(111)
	print('this is f2')
end

-- 把函数f2当做参数传给f1
f2(f1)

output:
this is f1
111
this is f2
----------------------------------------
-- return 可以有多个值,接收变量也秉持“多者忽略,少者补nil”的原则

function f()
	return 1,2
end
--  返回接收变量多于返回值
a,b,c=f()
print(a,b,c)

output:
1	2	nil

-- 返回接收变量少于返回值
a=f()
print(a)

output:
1
----------------------------------------
-- 可变参数:...来表示可变参数
function f(...)
	-- 把可变参数整体赋值给一个变量,vs为一个table,key是从1开始的自增,value为传递的参数
	vs = {...}
	-- select("#",...)可以用来获取可变参数列表的长度
	select("#",...)
end
  1. 运算符
- 算术运算符:+,-,*,/,%,^
 - 关系运算符:==,~=,>,<,>=,<=
 - 逻辑运算符:and or not
 - 其他运算符:
 	1   ..:两个字符串的拼接
 	2	#:返回长度
  1. 字符串
str='abc'
str="abc"
str=[[abc]]
  1. 迭代器
    基本定义:
迭代器提供了可以迭代遍历集合元素的方法。在lua中,集合包括可以用table来表示的一切形式

基本用法

  • ipairs:从前往后遍历,直到遇到一个非数字key,即停止遍历
  • pairs: 不关心key的类型,从前往后的遍历
tb={'a','b'}
tb['k1']='v1'
table.insert(tb, 'c')
for k,v in ipairs(tb) do
	print(k,v)
end
output:
1	a
2	b
3	c

for k,v in pairs(tb) do
	print(k,v)
end

output:
1	a
2	b
3	c
k1	v1

无状态的遍历

对于无状态的遍历,in后面的表达式会返回3个值,分别是迭代函数,状态常量,控制变量,如果实际表达式的返回值不足三个的时候,那么从前往后缺的值补nil,多出的部分就会自动忽略掉。所以in后面的表达式也可以用一个由返回值的function来替代。针对于迭代并不是in后面的表达式在迭代,而是由for来控制整个迭代过程。in后面的表达式也只会在初始的时候执行一次,返回3个值。在之后的迭代过程中,真正执行的是迭代函数,而迭代函数会返回两个变量,一个是key,一个是value,之后的执行过程都是迭代函数(key,value)。例如lua的内置函数就是这样的例子。直到返回的value为nil的时候,那么就标识迭代的结束。因为key和value都返回了,所以遍历到什么位置也就知道,并不需要迭代函数内部去记录迭代的状态,这就被称为是无状态的遍历

-- 内置函数ipairs的模拟实现:
function iter(a, i):
	i = i+1;
	-- 当元素不是nil的时候返回
	if(a[i]) then
		-- 返回两个变量,key和value 
		return i, a[i]
	end
end


function pairs(tb):
	return iter, tb, 0

mytb={'a','b'}
for k,v in pairs(mytb):   -- 这一步等价于for k,v in iter(mytb, 0)
	-- 循环体内这里的每一步都等价于iter(mytb,k);因为这里用的索引key都是当做参数,返回值来回传递的,iter无需记录其变化过程。所以这样的迭代被称为是无状态的迭代
	print(k,v)

output:
1	a
2	b

有状态的遍历

所谓的有状态的遍历,是相较于上面说的无状态的遍历而言。一般来说有状态的遍历是封装成一个闭包或者是table来使用的。即函数会自己来记录迭代的状态,即迭代到哪一步了,每一次的返回值都只有value。有状态的迭代相较于无状态的迭代来会消耗更多的资源,就如闭包创建的资源。但是有状态的遍历的好处就在于使用者不需要关心具体的遍历索引。只要拿到我们所需要的值就可以,而且因为是函数内部对状态进行处理,所以一些复杂的逻辑可以封装在函数内部。可以说是用资源的消耗来换取了操作的便利性

function iter(tb):
	local index=0	-- 定义索引变量,初始值为0
	local count=#tb	-- 定义迭代长度变量,值为table的长度
	-- 定义闭包函数
	return function()
		index=index+1	
		if index<count then 
			return tb[index]
		end
	end
end

mytb={'a','b'}

for v in iter(mytb) -- iter非闭包函数部分,如上面的local变量定义的地方,只是在这里执行一次
do
	-- 在循环体内,一直循环执行的是闭包函数部分,所以闭包函数也是主要封装逻辑的地方
	print(v)
end

output:
a
b
  1. table
    常用场景:
- 定义list
 - 定义k,v结构
 - module的定义
 - package的定义
 - object的定义

基本操作:

table其实是一种k,v的数据结果。在table中,key可是是任意类型,多类型也可以同时存在在一个table中。
-- table的定义
tb = {"a","b"} -- 不指定key的时候,key默认是从0开始的自增。这样的定义也可以理解为是数组的定义
-- 增加元素
tb[2]="c"
tb["k"]="v"
table.insert (tb, "d") -- 默认是在最后面增加元素
table.insert (tb, 2, "e") -- 在索引下标为2的为值增加元素,原来的元素一次后移
-- 删除元素
tb[3]=nil
table.remove(tb) --默认删除最后一个元素
table.remove(tb,3) -- 删除指定索引为3的元素
-- table变量赋值
tb2=tb
tb=nil  -- 当table通过变量赋值的时候,tb2和tb是指向同一片内存的,那么这个时候,如果把tb置为nil的时候,tb2依然可以访问到实际的变量值。因为把tb置为nil,只是取消了tb到变量值这块内存的指向,但不影响tb2,因为tb的值为nil,而且也没有其他地方使用tb,所以tb很快就会被lua的垃圾回收机制清理

-- table的排序
table.sort(tb2) -- 这里的排序是根据value来进行排序的
-- table 的value元素拼接
table.concat (tb, [, sep [, start [, end]]])
-- tb指的是拼接的table
-- sep 指的是value拼接的分隔符,可选,默认是空
-- start 指的是拼接的开始位置,可选,默认是0
-- end 指的是拼接的结束位置,可选,默认是table的长度
  1. module
lua 中module即模块管理机制,可以将一些公用的代码封装在一个模块中,以API的方式提供给其他的模块使用
	模块的定义本质上是一个table的定义,	由变量和函数组成,最后return table就可以
 注意:模块准备提供给外部使用的变量和函数都不能定义成是local,因为local只能在模块内部局部使用
-- 模块的定义
module = {}
-- 模块中常量的定义
module.constant="this is a constant"
-- 模块中函数的定义
function module.fun2()
	xxxx
end
-- 返回模块定义
return module

module的使用:

-- 引入模块
require("mymodule") as mymodule 
-- 调用模块常量
print(mymodule.constant)
-- 调用模块函数
mymodule.fun2()
  1. 协同程序(下面简称协程)

相关定义:

协程拥有独立的堆栈,独立的局部变量,独立的指令指针
	在同一时间只能有一个协程在执行,只有在明确指定协程挂起的时候他才会挂起
	协程的状态:
		- running:运行态
		- suspend:挂起态
		- dead:死亡

基本操作:

-- 创建一个协程,这个时候协程的状态是suspend,这里的参数fun在激活的时候会被调用,所使用的参数也是在resume的时候传入的。这里的fun也是协程具体的执行内容
co = coroutine.create(
	function(i)
		xxxx
	end
)
-- 激活协程,会将协程的状态从suspend修改为running,co之后的参数都是传给create(fun)中的函数的,激活协程的时候回调用create的参数
coroutine.resume(co, i)
-- 查看协程的状态,当协程执行完成(create(fun)的参数体执行完成的时候即协程执行结束),协程的状态会从running修改为dead
coroutine.status(co)
print("--------------------------------------------------------------")
-- 创建协程的第二种方式,与第一种不同的是这里返回的不是协程,而是create的参数函数
co_fun=coroutine.wrap(
	function(i)
		xxxx
	end
)
-- 第二种方式,直接调用函数就可以激活协程,调用函数的参数也是直接传入,
co_fun(1)

-- 返回一个正在执行的协程号
coroutine.running()
-- 协程挂起,即将running修改为suspend
coroutine.yield()

如果是使用yield()方法来暂停协程的话,那么resume()的返回值是yield的参数
coroutine.resume(co, i)   ----- 8
coroutine.yield(2*4)
使用resume来激活一个因为yield而暂停的协程的时候,yield的返回值是resume的参数

函数

条件

返回值

create

none

coroutine

resume

协程create之后

true/false

resume

协程yield()

true/false

resume

协程yield(akws)

true/false,awks

yield

被resume(awks)激活

awks

通过上面的分析我们可以看到,yield和resume的交替可以实现协程内部和外部的参数传递的功能