Lua配置、安装、与运行
1.进入Lua官网:http://www.lua.org——下载Lua
2.下载文件【 lua-5.3.4_Win64bin.zip 】
3.创建一个空文件夹“Lua”并在其中解压【 lua-5.3.4_Win64bin.zip 】压缩文件
4.复制“Lua”文件夹到一个不会被删除的地方,
5.路径最好不要是中文。( 推荐选择C盘 )
6.将此路径加入到环境变量中
7.cmd 中输入lua 查看安装是否成功
Lua编译与调试环境搭建
1.下载sublime
2.点击 菜单栏→→ 工具 →→ 编译系统 →→ 新编译系统
menu bar →→ Tools →→ Build System →→ new Build System
3.复制代码到配置中
"cmd": ["lua","$file"],
"file_regex":"^(...*?):([0-9]*):?([0-9]*)",
"selector":"source.lua"
3.保存到默认目录:命名为MyLua.sublime-build
注意:后缀一定要是 .sublime-build 。
保存,关闭Sbulime Text
4.重新打开Sbulime Text
点击 菜单栏→→ 工具 →→ MyLua(我们刚创建好的编译系统文件)
menu bar →→ Tools →→ MyLua
选中MyLua编译环境就可以运行了
5.保存完成→→点击“F7”或者“Ctrl+B”调试
Lua基本语法
1.交互式编程
Lua 提供了交互式编程模式。我们可以在命令行中输入程序并立即查看效果。
Lua 交互式编程模式可以通过命令 lua -i 或 lua 来启用:
2.脚本式编程
我们可以将 Lua 程序代码保存到一个以 lua 结尾的文件,并执行,该模式称为脚本式编程,如我们将如下代码存储在名为 hello.lua 的脚本文件中:
Lua中的数据类型
1.数据类型展示
print(type(“Hello world”)) --> string
print(type(10.4*3)) --> number
print(type(print)) --> function
print(type(type)) --> function
print(type(true)) --> boolean
print(type(nil)) --> nil
print(type(type(X))) --> string
2.注意事项
--返回值判断类型
if boostr == "true" then
elseif nilstr=nil then
end
Lua中的变量与函数
全局变量
局部变量
非局部变量(先看闭包)
变量值的交换
Lua中的函数
通用理解
函数:
1.在Lua中有一个容易混淆的概念是,函数与所有其他值一样都是匿名的,即他们都没有名称。当讨论一个函数名时(例如print)。实际上是在讨论持有某函数的变量,这与其他变量持有各种值一个道理
2.一个函数实际上就是一条语句(赋值语句),这条语句创造了一种类型为函数的值
高阶函数:基于First-Class-Value的应用体现
可以将表达式"function(x)<body> end"视为一种函数的构造式,就像table的构造式{
}一样。将这种函数构造式的结果称为一个”匿名函数”。
下面的示例显示了匿名函数的方便性,它的使用方式有些类似于Java中的匿名类,如:
table.sort(test_table,function(a,b) return (a.name > b.name) end)
像sort这样的函数,接受另一个参数作为实参的,称其是一个”高阶函数“,高阶函数是一种 强大的编程机制,
应用匿名函数来创建高阶函数所需的实参则可以带来更大的灵活性。高阶函数并没有什么特权。
Lua强调将函数视为”first-class valeu",所以,高阶函数只是基于该观点的应用体现而已。
闭包
简单来讲,一个闭包 就是一个函数加上该函数所需访问的所有“非局部变量”。
将函数和内部的第二个函数称为闭包。
function newCounter()
local i = 0
return function() --匿名函数
i = i + 1
return i
end
end
c1 = newCounter()
print("The return value of first call is " .. c1())
print("The return value of second call is " .. c1())
--输出结果为:
--The return value of first call is 1
--The return value of second call is 2
1.闭包函数所返回的值仍然被保留并可用于下一次计算
2.Lua每次在给新的闭包变量赋值时,都会让不同的闭包变量拥有独立的"非局部变量"
function newCounter()
local i = 0
return function() --匿名函数
i = i + 1
return i
end
end
c1 = newCounter()
c2 = newCounter()
print("The return value of first call with c1 is " .. c1())
print("The return value of first call with c2 is " .. c2())
print("The return value of second call with c1 is " .. c1())
--输出结果为:
--The return value of first call with c1 is 1
--The return value of first call with c2 is 1
--The return value of second call with c1 is 2
正确的尾调用
尾调用:goto到方法与直接调用函数创建新的栈的函数调用优化
若没有”尾调用消除“的话,每次用户的移动都会创建一个新的stack,若干步之后就有可能导致栈溢出
注意事项:
在Lua中支持这样一种函数调用的优化,即“尾调用消除”。我们可以将这种函数调用方式视为goto语句,如:
function f(x) return g(x) end
由于g(x)函数是f(x)函数的最后一条语句,在函数g返回之后,f()函数将没有任何指令需要被执行,因此在函数g()返回时,可以直接返回到f()函数的调用点。由此可见,Lua解释器一旦发现g()函数是f()函数的尾调用,那么在调用g()时将不会产生因函数调用而引起的栈开销。这里需要强调的是,尾调用函数一定是其调用函数的最后一条语句,否则Lua不会进行优化。然而事实上,我们在很多看似是尾调用的场景中,实际上并不是真正的尾调用,如:
function f(x) g(x) end --没有return语句的明确提示
function f(x) return g(x) + 1 --在g()函数返回之后仍需执行一次加一的指令。
function f(x) return x or g(x) --如果g()函数返回多个值,该操作会强制要求g()函数只返回一个值。
function f(x) return (g(x)) --原因同上。
在Lua中,只有"return <func>(<args>)"形式才是标准的尾调用,至于参数中(args)是否包含表达式,由于表达式的执行是在函数调用之前完成的,因此不会影响该函数成为尾调用函数。
函数原型
每个Lua函数都有一个原型,这是一个由GC管理的对象,它挂靠在函数上,为函数提供必要的信息,比如这个函数的操作码(opcodes),常量信息,本地变量信息,upvalue信息,和调试信息等等。
因为Lua函数中可以内嵌函数,所以原型对象里面也有一个内嵌原型的列表,由此形成一个函数原型的树。
原型结构是这样的:
typedef struct Proto {
CommonHeader;
// 固定参数的数量
lu_byte numparams; /* number of fixed parameters */
// 是否有可变参数
lu_byte is_vararg;
// 该函数需要的栈大小
lu_byte maxstacksize; /* number of registers needed by this function */
// upvalues数量
int sizeupvalues; /* size of