1.准备
1.简介
- 1.
Lua
是一种轻量小巧的脚本语言,用标准C
语言编写并以源代码形式开放
2.目标
- 1.其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能
3.特点
- 1.轻量级:用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可方便嵌入别的程序里
- 2.可扩展:
Lua
提供易于使用的扩展接口和机制:由宿主语言(C
/C++
)提供这些功能,Lua
可像内置功能一样使用- 3.支持面向过程(
procedure-oriented
)编程和函数式编程(functional programming
)- 4.自动内存管理,只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象
- 5.语言内置模式匹配;闭包(closure);函数也可以看做一个值;提供多线程(协同进程,并非操作系统所支持的线程)支持
- 6.通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等
4.应用场景
- 1.游戏开发
- 2.独立应用脚本
- 3.
Web
应用脚本- 4.扩展和数据库插件(
MySQL Proxy
和MySQL WorkBench
)- 5.安全系统(入侵检测系统)
5.环境安装
1.Linux系统
curl -R -O http://www.lua.org/ftp/lua-5.3.0.tar.gz tar zxf lua-5.3.0.tar.gz cd lua-5.3.0 make linux test make install
2.Mac系统
curl -R -O http://www.lua.org/ftp/lua-5.3.0.tar.gz tar zxf lua-5.3.0.tar.gz cd lua-5.3.0 make macosx test make install
3.Window系统
- 1.进入
Lua
官网:http://www.lua.org
- 2.点击
download
- 3.选择二进制文件
- 4.点击左边的
Download
并选择对应版本lua-5.4.2_Win64_bin.zip
进行下载
- 5.将对应压缩包解压到指定文件
- 6.配置环境变量
- 7.进入
cmd
进行测试
2.基础
1.交互式编程
- 1.默认使用交互式编程
- 2.交互式编程可以输入程序并立即查看结果
2.脚本式编程
- 1.将
Lua
程序保存到一个以lua
结尾的文件并执行- 2.如果
Lua
脚本文件有错误则内容都不会执行
3.注释
1.单行注释
--print("Hello World") print("Hello Lua")
2.多行注释
--[[ 多行注释 多行注释 --]]
4.标示符
- 1.
Lua
标示符用于定义一个变量,函数获取其他用户定义的项- 2.标示符以一个字母
A-Z
或a-z
或下划线_
开头,然后加上0
个或多个字母,下划线,数字(0-9
)- 3.
Lua
不允许使用特殊字符(@
、$
、%
)定义标示符- 4.不推荐使用下划线加大写字母的标示符,因为
Lua
的保留字也是这样- 5.一般约定以下划线开头连接一串大写字母的名字(
_VERSION
)被保留用于Lua
内部全局变量- 6.
Lua
是一个区分大小写的编程语言,因此Lua
中Runoob
与runoob
是两个不同的标示符
5.关键字
- 1.
Lua
保留关键字不能作为常量
或变量
或其他用户自定义标示符
and break do else elseif end false for function if in local nil not or repeat return then true until while goto
6.全局变量
- 1.默认情况下,变量总是认为是全局的
- 2.全局变量不需要声明,给一个变量赋值后即创建了这个全局变量
- 3.访问一个没有初始化的全局变量不会出错,只是得到的结果是
nil
- 4.如果想删除一个全局变量,只需要将变量赋值为
nil
;当且仅当一个变量不等于nil
时,这个变量即存在
3.数据类型
1.
Lua
是动态类型语言,变量不要类型定义,只需要为变量赋值2.值可以存储在变量中,作为参数传递或结果返回
3.
Lua
可以使用type
函数测试给定变量或者值的类型4.
Lua
中有8
个基本类型
数据类型 描述 nil
只有值 nil
属于该类,表示一个无效值(在条件表达式中相当于false
)boolean
false
和true
number
表示双精度类型的实浮点数 string
字符串由一对双引号或单引号来表示 function
由 C
或Lua
编写的函数userdata
表示任意存储在变量中的 C
数据结构thread
表示执行的独立线路,用于执行协同程序 table
Lua
中的表table
其实是一个关联数组associative arrays
;数组的索引可以是数字、字符串或表类型;Lua
中table
的创建是通过构造表达式来完成,最简单构造表达式是{}
,用来创建一个空表
1.nil(空)
1.
nil
类型表示没有任何有效值,它只有一个值nil
2.打印一个没有赋值的变量,便会输出一个
nil
值3.对于全局变量和
table
,nil
还有一个删除作用,将全局变量或table
表里的变量赋nil
值等同于删除4.
nil
作比较时应该加上双引号(type(X)==nil
结果为false
的原因是type(X)
实质是返回的nil
字符串是一个string
类型)
2.boolean(布尔)
- 1.
boolean
类型只有两个可选值:true
(真) 和false
(假)- 2.
Lua
把false
和nil
看作是false
,其他的都为true
,数字0
也是true
3.number(数字)
- 1.
Lua
默认只有一种number
类型 ->double
(双精度)类型(默认类型可以修改luaconf.h
里的定义)
4.string(字符串)
- 1.字符串由一对双引号或单引号来表示
- 2.或者使用
2
个方括号[[]]
来表示一块字符串- 3.对一个数字字符串进行算术操作时,
Lua
会尝试将该数字字符串转换成一个数字- 4.字符串连接使用的是
..
- 5.使用
#
计算字符串的长度并且放在字符串前面
5.table(表)
- 1.
Lua
中table
的创建是通过构造表达式
来完成,最简单构造表达式是{}
,用来创建一个空表- 2.
table
也可以创建时在表里添加数据直接初始化表- 3.
Lua
中的表table
其实是一个关联数组associative arrays
,数组的索引可以是数字
或字符串
(表类似集合)- 4.如果遍历则第一个参数默认为索引,第二个参数为
value
- 5.不同于其他语言的数组把
0
作为数组的初始索引,Lua
中表的默认初始索引以1
开始- 6.
table
不会固定长度大小,有新数据添加时table
长度会自动增长(注意:#只能统计索引为数字的长度
),没初始的table
都是nil
6.function(函数)
- 1.
Lua
中函数被看作是第一类值First-Class Value
,函数可以存在变量中- 2.
function
可以以匿名函数anonymous function
的方式通过参数传递
7.thread(线程)
- 1.
Lua
中最主要的线程是协同程序coroutine
- 2.类似线程
thread
,拥有自己独立的栈、局部变量和指令指针- 3.可以跟其他协同程序共享全局变量和其他大部分东西
- 4.线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起
suspend
时才会暂停
8.userdata(自定义类型)
- 1.
userdata
是一种用户自定义数据,用于表示一种由应用程序或C/C++
语言库所创建的类型- 2.其可以将任意
C/C++
的任意数据类型的数据(通常是struct
和 指针)存储到Lua
变量中调用
4.变量
- 1.变量在使用前需要在代码中进行
声明
,即创建该变量- 2.编译程序执行代码之前
编译器
需要知道如何给语句变量开辟存储区
,其用于存储变量的值- 3.
Lua
变量有三种类型
- 1.
全局变量
- 2.
局部变量
- 3.
表中的域
- 4.变量的默认值均为
nil
1.全局变量
- 1.
Lua
中的变量全是全局变量,哪怕是语句块或是函数里,除非用local
显式声明为局部变量- 2.
Lua
语言中,全局变量无须声明即可使用,使用未经初始化的全局变量不会导致错误- 3.当使用未经初始化的全局变量时,得到的结果为
nil
2.局部变量
- 1.只有使用
local
显式声明的才是局部变量- 2.局部变量的作用域为从声明位置开始到所在语句块结束
- 3.尽可能的使用局部变量,有两个好处
- 1.避免命名冲突
- 2.访问局部变量的速度比全局变量更快
3.变量赋值
- 1.
Lua
可对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句右边的值会依次赋给左边的变量- 2.遇到赋值语句
Lua
会先计算右边所有的值然后再执行赋值操作,所以可以快捷交换变量的值
- 3.当变量个数和值的个数不一致时,
Lua
会一直以变量个数为基础采取以下策略
- 1.变量个数 > 值的个数 ->
按变量个数补足nil
- 2.变量个数 < 值的个数 ->
多余的值会被忽略
- 4.如果要对多个变量赋值必须依次对每个变量赋值
- 5.多值赋值经常用来交换变量,或将函数调用返回给变量
- 6.
Lua
对多个变量同时赋值,不会进行变量传递,仅做值传递
5.循环
- 1.循环结构是在一定条件下反复执行某段程序的流程结构,被反复执行的程序被称为循环体
- 2.循环语句是由
循环体
及循环的终止条件
两部分组成的
1.while循环
while(condition) do statements end
- 1.
Lua
中while
循环语句在判断条件为true
时会重复执行循环体语句- 2.
statements
(循环体语句) 可以是一条或多条语句,condition
(条件) 可以是任意表达式,当condition
(条件) 为true
时执行循环体语句
2.for循环
- 1.
Lua
中for
循环语句可以重复执行指定语句,重复次数可在for
语句中控制- 2.
Lua
编程语言中for
语句有两大类
- 1.数值
for
循环- 2.泛型
for
循环
1.数值for循环
for var=exp1,exp2,exp3 do <执行体> end
- 1.
var
从exp1
变化到exp2
,每次变化以exp3
为步长递增var
,并执行一次执行体
- 2.其中
exp3
是可选的,如果不指定则默认值为1
- 3.
for
的三个表达式在循环开始前一次性求值(例:函数f(x)
只在循环开始前执行一次),以后不再进行求值
2.泛型for循环
--打印数组a的所有值 a = {"one", "two", "three"} for i, v in ipairs(a) do print(i, v) end
- 1.泛型
for
循环通过一个迭代器函数来遍历所有值,类似java
中的foreach
语句- 2.
i
是数组索引值,v
是对应索引的数组元素值。ipairs
是Lua
提供的一个迭代器函数,用来迭代数组
3.repeat…until循环
repeat statements until( condition )
- 1.
Lua
中repeat...until
循环语句不同于for
和while
循环- 2.
for
和while
循环的条件语句在当前循环执行开始时判断,而repeat...until
循环的条件语句在当前循环结束后判断- 3.因为循环条件判断语句
condition
在循环体末尾部分,所以在条件进行判断前循环体都会执行一次- 4.如果条件判断语句
condition
为false
,循环会重新开始执行,直到条件判断语句condition
为true
才会停止执行
4.嵌套循环
for init,max/min value, increment do for init,max/min value, increment do statements end statements end
while(condition) do while(condition) do statements end statements end
repeat statements repeat statements until( condition ) until( condition )
5.break语句
- 1.
Lua
中break
语句插入在循环体中,用于退出当前循环或语句,并开始执行紧接着的语句- 2.如果你使用循环嵌套,
break
语句将停止最内层循环的执行,并开始执行的外层的循环语句
6.goto语句
goto Label -- Label 的格式 :: Label ::
- 1.
Lua
中的goto
语句允许将控制流程无条件地转到被标记的语句处- 2.
lable
中可以设置多个语句- 3.使用
goto
可以实现continue
的功能
6.流程控制
- 1.
Lua
控制语句通过程序设定一个或多个条件语句,条件为true
时执行指定程序代码,条件为false
时执行其他指定代码- 2.控制结构的条件表达式结果可以是任何值,
Lua
认为false
和nil
为假,true
和非nil
为真,且Lua
中0
为true
1.if语句
2.if…else语句
3.if 嵌套语句
模块与包
- 1.模块类似于一个封装库,从
Lua 5.1
开始Lua
加入了标准的模块管理机制- 2.模块可把一些公用的代码放在一个文件里,以
API
接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度- 3.
Lua
的模块是由变量、函数等已知元素组成的table
- 4.因此创建一个模块很简单,就是创建一个
table
,然后把需要导出的常量、函数放入其中,最后返回这个table
就行- 5.模块的结构就是一个
table
的结构,因此可以像操作调用table
里的元素那样来操作调用模块里的常量或函数- 6.可使用
local
声明变量为程序块的局部变量,即表示一个私有函数,因此是不能从外部访问模块里的这个私有函数,必须通过模块里的公有函数来调用
1.require函数
- 1.
Lua
提供了一个require
的函数用来加载模块- 2.执行
require
后会返回一个由模块常量或函数组成的table
,并且还会定义一个包含该table
的全局变量- 3.其中require中引用的是
Lua
的文件名,而不是模块名,全局变量引用的是模块名,而不是文件名- 4.可以加载的模块定义一个别名变量方便调用
3.加载机制
- 1.对于自定义的模块,模块文件不是放在哪个文件目录都行,函数
require
有自己的文件路径加载策略- 2.其会尝试从
Lua
文件或C
程序库中加载模块- 3.
require
用于搜索Lua
文件的路径是存放在全局变量package.path
中- 4.当
Lua
启动后会以环境变量LUA_PATH
的值来初始这个环境变量- 5.如果没有找到该环境变量,则使用一个编译时定义的默认路径来初始化
- 6.如果找到目标文件,则会调用
package.loadfile
来加载模块,否则就会去找C
程序库- 7.搜索的文件路径是从全局变量 package.cpath
获取,而这个变量则是通过环境变量
LUA_CPATH`来初始- 8.搜索策略跟上面的一样,只不过现在换成搜索的是
so
或dll
类型的文件,如果找到那么require
会通过package.loadlib
来加载