Lua学习

本文详细介绍Lua环境的搭建步骤,包括Lua解释器的下载、配置及版本验证。阐述Lua的词法规范、数据类型、表达式、控制结构、函数等核心概念。深入探讨Lua的特性,如闭包、非全局函数定义和尾调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 执行环境安装

Lua解释器下载地址:http://luabinaries.sourceforge.net/

下载完成后解压缩到想要的目录即可。解压缩完成之后,如果想要在任何目录都可以运行lua解释器,可以将lua解释器所在目录加入Path环境变量。

然后在命令行窗口输入lua53.exe –v可以查看lua的版本信息

Lua代码可以通过两种方式执行,一种是编写脚本通过lua解释器执行,还有一种就是在命令行窗口直接输入lua53.exe回车,然后会进入命令模式,可以直接执行lua语句,想退出命令模式可以通过执行os.exit()函数或者根据linux系统按Ctrl+D或Windows系统按Ctrl+Z退出。可以在代码所在文件夹按住shift右键选择在此处打开Powershell窗口菜单,然后执行lua脚本。

  • 语法
  1. 词法规范

1.1Lua是区分大小写的,变量名不能以数字开头,也不能定义为Lua的保留字。

1.2Lua的单行注释以”--”两个连字符开始,多行注释以”—[[”两个连字符和两个英文左中括号开始,以”]]”两个英文右中括号结束。

--print("单行注释")
--[[print("第一行")
print("第二行")
]]

1.3Lua的语句可以不用分号结尾,当然也可以使用分号结尾

1.4Lua中全局变量不需要申明,只需要将一个值赋给变量就可以了,直接使用未初始化的变量不会出错,访问结果是一个特殊的值nil,例如:

可以通过给全局变量赋值nil的方式删除全局变量。

1.5可以通过解释器名称后跟参数或文件名的方式来运行,比如修改命令提示符:

在linux系统中可以在lua脚本文件第一行加上#!/usr/local/bin/lua,这样就可以不通过lua命令直接执行lua脚本。

在交互模式中可以通过等号跟上表达式的方式直接打印表达式的结果,不需要通过print函数打印

2.1类型和值

Lua中定义变量不需要定义变量的类型,Lua可以根据变量的值确定变量的类型。Lua中有8种数据类型:nil(空)、boolean(布尔)、number(数字)、string(字符串)、userdata(自定义类型)、function(函数)、thread(线程)、table(表)。

2.1.1对于boolean类型的变量,只有false和nil值是假,其他任何值都是真。

2.1.2对于字符串类型的变量,通常以单引号或双引号表示,Lua不能直接修改字符串的某个字符,而是会创建新字符串,字符串的回收由自动内存管理机制控制,不需要开发人员关心,Lua处理字符串的效率很高,因此在Lua程序中处理100K或1M的字符串很常见。

Lua中以一对双方括号来界定一个跨行的字符串。

page=[[
<html>
	<head>
		<title>An HTML Page</title>
	</head>
	<body>
		<a href="http://www.lua.org" >Lua</a>
	</body>
</html>
]]

print(page)

在Lua中字符串连接符是..,因此如果将字符串数字和数字相加得到的数字,不是字符串。

在Lua中字符串和数字是两样不同的东西,比如1=”1”得到的结果就是false,因此最好将同类型的数据进行比较,如果想要将字符串显示的转换为数字可以使用tonumber()函数,如果字符串无法转换为数字会返回nil。如果想要将数字转换成字符串可以使用tostring()函数或将数字与空字符串””相连。

如果想要获取字符串的长度,可以通过在字符串前加上#来获取。

2.1.3table可以理解为数组+映射的数据结构,其中可以通过索引获取值或通过键获取值。

Lua中也是通过table来表示模块、包、对象的。比如输入io.read的时候,表示“io模块的read函数”,即通过字符串read作为键来索引表io。

Table永远是匿名的,一个持有table的变量和table自身没有固定的关联性,如果没有任何一个变量引用table了,这个table就会被Lua的垃圾收集器回收。

下面是几种长度操作符"#"对table的操作

a={}
a[1]=1
print(a[#a])--打印列表a的最后一个值
a[#a]=nil--删除最后一个值
a[#a+1]=v--将v添加到列表末尾

3.1表达式

3.1.1介绍一些和Java语言不同的部分,比如Lua中的不等号是”~=”,Lua中的相等性比较会同时比较类型和值。nil只和自身相等。字符串是按字母次序进行比较。Table类型比较的是引用。

3.1.2逻辑操作符有and、or、not,除了false和nil是假,其他都是真。其中Lua的逻辑操作符是短路的。

3.1.3table构造式

构造式是用于创建和初始化table的表达式。这是lua特有的一种表达式。最简单的构造式是空构造式{},用于创建一个空table。构造式还可以用于初始化数组。比如

polyline={color="blue",thickness=2,npoint=4,
	{x=0,y=0},
	{x=2,y=0},
	{x=2,y=1},
	{x=0,y=1}
}

print(polyline[1].x)
print(polyline[3].y)
print(polyline["color"])
a="thickness"
print(polyline[a])

在table中,最后一个元素后面也可以跟上逗号,这是因为这样就不需要对最后一个元素做特殊处理了。在一个构造式中也可以用分号代替逗号来分隔构造式中不同的成分。

4语句

4.1赋值

Lua允许多重赋值,即同时将多个值赋给多个变量,每个值和变量之间用逗号隔开:

a,b=1,2

赋值后变量a为1,变量b为2

在多重赋值中Lua先对等号右边的所有元素求值,然后才执行赋值,这样便可以用一句多重赋值来交换两个变量了:

a,b=1,2
a,b=b,a

Lua会将等号两边的值和变量个数调成一致,如果左边变量个数小于右边值的个数,那么就自动剔除右边多余的值。如果左边变量的个数大于右边值的个数,那么多余的变量就赋值nil。

多重赋值主要用于变量交换值和接受函数的多个返回值。

4.2局部变量

相对于全局变量,Lua还提供了局部变量,通过local定义:

a=10 --全局变量
local b=20 --局部变量

局部变量的作用域仅限于声明他们的那个块。一个块是一个控制结构的执行体、或者是一个函数的执行体或者是一个程序块:

x=10
local i=1
if i<20 then
	local x
	x=20
	print(x+1)
else
	print(x)
end
print(x)

在交互模式中执行的代码每行自成一个程序块,因此如果想要局部变量在一段代码块中有效可以通过do end包住代码实现。

尽量使用局部变量,局部变量可以避免将一些无用的名称引入全局环境,而且访问局部变量比访问全局变量块,且局部变量随着作用域的结束而消失,有利于垃圾收集器回收内存。

有一种写法是local foo=foo,这个语句的意思是将全局的变量foo的值赋给局部变量foo,如果后续有其他函数修改了全局foo的值,可以通过局部变量foo保存原始值,且这种方式还可以加速在当前作用于对foo的访问。

4.3控制结构

4.3.1Lua的控制结构包括用于条件执行的if,用于迭代的while、repeat和for。其中if、while和for以end结束,repeat以until结束。

4.1.2如果要编写嵌套的if可以使用elseif。

4.1.3repeat用于重复执行循环体内的语句知道条件为真时结束,因此其中的循环体至少会执行一次,而while是先判断再执行,因此repeat可以理解为do..while。

4.1.4数字型for

for语句有两种形式:数字型for和泛型for

数字型for语法如下:

for var=exp1,exp2,exp3 do

<执行体>

end

var从exp1变化到exp2,每次变化以exp3作为步长并执行一次执行体,第三个表达式exp3是可选的,如果不指定的话,步长默认为1,如果不想给循环设置上限的话,可以使用math.huge,通过break终止循环:

for i=1,math.huge do
	if(i+i>400) then
		print(i)
		break
	end
end

4.1.5泛型for

泛型for通过一个迭代器函数循环遍历所有的值:

--打印数组a的所有值
for i,v in ipairs(a) do print(v) end
--打印table中所有的key
for k in pairs(t) do print(k) end

4.4break和return

break用于跳出当前循环,不会改变多层循环,return用于从函数返回结果,因此每个函数都有一句隐式的return。如果一个函数没有返回值,那么也不需要在结尾添加return语句。

因为break和return后的语句不会被执行到,因此Luabreak和return位于所属代码块的最后一行,如果想要调试函数,但是又不想执行函数的内容,可以用do end包住return语句。

5.函数

函数都需要带一对括号,即使没有参数,有一种情况可以不带括号,就是一个函数只有一个参数,且这个参数是一个字面字符串或table构造式,那么圆括号可以省略。

print “hello world” --字面字符串
f {x=10,y=20} --table构造式

Lua为面向对象式的调用提供了一种特殊的语法—冒号操作符。表达式o.foo(o,x)的另一种写法是o:foo(x),冒号操作符使调用o.foo时将o隐含的作为函数的第一个参数。

Lua程序既可以使用Lua编写的函数,也可以调用以C语言编写的函数。所有的Lua标准程序库中的函数都是C语言编写的。对Lua编写的函数和C语言编写的函数调用,在语法上是没有区别的。

调用函数时提供的实参数量可以和形参数量不同,Lua会自动调整实参数量,以匹配参数列表的要求,如果实参不足,多余的形参初始化为nil。

5.1Lua允许函数返回多个结果

比如用于在字符串中定位一个模式的函数string.find。该函数若在字符串中找到了匹配的模式,就返回匹配的起始字符和结尾字符的索引。

s,e=string.find(“hello Lua users”,”Lua”)

function maxnum(a)
	local mi=1
	local m=a[mi]
	for i,v in ipairs(a) do
		if v> m then
			mi,m=i,v
		end
	end
	return m,mi
end
print(maxnum({5,4,8,12,43,32}))

关于函数的多重返回值在不同场景下的行为有很多规则,这里不一一记录了。

5.2变长参数

Lua中的函数还可以接受不同数量的实参,参数列表用三个点表示…

6.深入函数

在Lua中,函数与所有其他值一样都是匿名的,即他们都没有名称。当讨论一个函数名时比如print,实际上在说一个持有某个函数的变量。

p=print
p(“hello world”)

一个函数定义就可以理解为一个赋值语句,这条语句创建了一个类型为函数的值,并将这个值赋值给一个变量。

关于函数还可以深入了解闭合函数、非全局函数定义(尤其注意关于递归调用的非全局函数)和尾调用(避免栈溢出)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值