Lua第一部分语言总结

参考Programming in Lua,学习Lua的第一部分语言总结

一、chunks:一组放在一起的语句组。


二、全局变量:与nil相关。一个全局变量不是nil的时候即存在,是nil的时候即不存在。所以全局变量本身不需声明,与C++相比灵活。


三、八种变量:

1、nil:表示这个值没有

2、booleans:false和nil表示假,其余所有都是真

3、numbers:任意实数

4、string:单双引号都可以表示字符串,习惯使用双引号。字符串不可修改,即将a="one string"的one改为another,需要重新为a赋值,b=string.grusb(a,"one","another")。但是a不会改变。

string和number之间用是自动转换的

5、function:声明函数。可以认为任何一个函数都是一个变量。

6、userdata:后补充

7、thread:后补充

8:table:

(1)构造函数仅仅用于初始化,之后可以添加或删除

(2)无法调用的使用索引调用,且这一部分数据自己从1开始计算索引。

<span style="font-size:18px;">a={"xxx",x=1,y=2,"yyy"}

print(a[1])
print(a.x)
print(a.y)
print(a[2])
print(a[3])</span>
输出:

xxx
1
2
yyy
nil


四、运算符:

1、a==b:a和b类型不同则必不相同;Lua的比较通过引用比较,赋值也是通过引用赋值。所以,a和b声明内容相同(table,如果声明为一个普通内置变量则不成立),==时却不同。用a给c赋值,则a==c为真。

2、二元逻辑运算符,通过前一个元判断整体。若前一个元可以决定整体就返回前一个元,否则返回后一个元:

a and b:a为false则返回a,否则返回b

a or b:a为true则返回a,否则返回b

C++中的三元运算:a?b:c

lua中的三元运算:(a and b) or c


五、局部变量与代码块

local:局部变量,只在代码块中有效;在某些地方,使用类似于C++中的static

代码块:一个chunk,类似于C++中的{}。用do...end可以表示{}。

局部变量的使用主要要和注意交互模式,在交互模式中可以使用do...end可以表示{}。


六、控制语句

1、与C++相比,用repeat...until代替了do...while

2、for有两类

(1)数值for循环:

for i=var1(开始),var2(终止),var3(步长,默认1,可省略) do

end

以上声明方式导致var都是for的local,出了for就没用了

三个var只在循环开始前做一次计算,不再修改


(2)泛型for循环:遍历迭代子函数返回的每一个值,后补充


七、函数

1、可以多个返回值。当函数调用是参数中的唯一参数或者最后一个参数的时候,尽量多的返回返回值;其余情况下只能返回第一个值。

<span style="font-size:18px;">function foo()
	return 1,2;
end

x,y=foo(),3

print(x)
print(y)</span>
打印1,3

<span style="font-size:18px;">function foo()
	return 1,2;
end

a={foo(),3}
print(a[1])
print(a[2])
print(a[3])</span>
打印 1,3,nil

2、函数的命名参数的使用:简而言之就是将多个参数放到一个表中,在函数中,通过表调用函数

<span style="font-size:18px;">nametable={oldname="old",newname="new"}

function rename(arg)
	return os.rename(arg.oldname,arg.newname)
end</span>
3、高级函数:函数的参数中有另一个函数即称为是高级函数

4、关于闭包:一个嵌套在函数的函数和其外部函数中的local变量共同构成

<span style="font-size:18px;">function counter()
	local i=0;  --<span style="color:#ff0000;">类似于C++中的static</span>
	return function()   --匿名函数
		i=i+1;
		return i;
	end
end

c1=counter();
c2=counter();

print(c1());  --c1作为一个闭包
print(c1());  --同一个c1闭包
print(c2());  --另一个闭包c2
</span>
输出:

1
2
1

对比:

<span style="font-size:18px;">function add(i)
	i=i+1;
	return i;
end

function counter()
	local i=0;
	return add(i);

end

c1=counter();
c2=counter();

print(c1);  --c1作为一个闭包
print(c1);  --同一个c1闭包
print(c2);  --<span style="font-family: KaiTi_GB2312;">同</span>一个闭包
</span>

输出:

1
1
1

对比:

<span style="font-size:18px;"><span style="background-color: rgb(255, 255, 255); font-family: KaiTi_GB2312; font-size: 18px;"></span><pre name="code" class="plain">function counter()
	i=0;  --类似于C++中的static
	return function()   --匿名函数
		i=i+1;
		return i;
	end
end

c1=counter();
c2=counter();

print(c1());  --c1作为一个闭包
print(c1());  --同一个c1闭包
print(c2());  --另一个闭包c2</span>

 

输出:

123

5、局部函数递归定义的时候需要先声明再使用,否则在调用递归的时候会先寻找全局函数中相同名字的函数寻求调用:

<span style="font-size:18px;">function fact(n)
	return n;
end

local fact=function(n)
	if n==0 then
		return 1;
	else
		return n*fact(n-1);
	end
end

print(fact(5))
</span>
输出是20。表示第一次调用的是local,递归的第一次调用是全局的fact

6、尾调用:函数的最后一个动作是调用其他函数,像是goto一样

<span style="font-size:18px;">function f()
	return g();
end</span>
调用g()后,不需要再栈中保留f的相关信息,所以尾调用用于递归可以无限制。


八、迭代器

迭代器支持指针类型的结构,遍历集合所有元素,使用函数描述迭代器,每次调用迭代器函数都要返回集合的下一个元素。迭代器保留上一次成功调用的状态和下一次成功调用的状态。

闭包:闭包本身+创建闭包的工厂

迭代器要和闭包结合起来,代码如下:

<span style="font-size:18px;">function list_liter(t)   --创建闭包的工厂
	local i=0;
	local n=table.getn(t);
	return function()   --和以上的两个local构成一个闭包,即通过i保存了每上一次和下一次的所有调用状态
		i=i+1;
		if i<=n then
			return t[i];
		end
	end
end

t={1,2,3};
itor=list_liter(t);

while true do
	local element=itor();

	if element==nil then
		break;
	end

	print(element);
end
</span>

迭代器可以分为无状态的迭代器和多状态的迭代器,但是尽量写无状态迭代器;其次使用闭包。尽量不用使用table的多状态迭代器。


九、泛型for

上一个代码例子可以用泛型for遍历

<span style="font-size:18px;">function list_liter(t)
	local i=0;
	local n=table.getn(t);
	return function()   --和以上的两个local构成一个闭包,即通过i保存了每上一次和下一次的所有调用状态
		i=i+1;
		if i<=n then
			return t[i];
		end
	end
end</span>
<span style="font-size:18px;">t={1,2,3};
for elemment in list_liter(t) do
	print(elemment)
end</span>

(1)泛型for的表达式:

for <var-list> in <exp-list> do
<body>
end
<var-list>:变量列表名列表,第一个变量是控制变量,为nil的时候循环结束

<exp-list>:表达式列表,一般只有一个值,就是迭代工厂
(2)运行步骤:

[1]计算表达式,返回三个值,迭代函数,状态常量,控制变量

[2]调用迭代函数,参数是状态常量和控制变量

[3]将迭代函数的返回值赋值给变量列表,检查控制变量

<span style="font-size:18px;">for var1,var2,...,varn in explist --var1是控制变量
	do block
end</span>
以上代码等价于

<span style="font-size:18px;">do
	local f,s,var=explist --f表示迭代函数,s表示状态常量,var控制变量
	while true do
		local var1,var2,...,varn=f(s,var);
		var=var1
		
		if var==nil then
			break;
		end
	end
end</span>


九、dofile,loadfile,loadstring,require区别:

Lua将代码预编译为中间码再执行。解释型语言的特征是编译器是语言运行时的一部分。

dofile:编译+执行。可以认为是loadfile+错误保护机制。每次编译每次执行。

loadfile:编译但不执行,本身就可以返回错误信息。一次编译多次运行。

loadstring:功能强大但陷阱多。读入一个字符串当做一个函数做处理

require:类似于dofile,但是会搜索目录加载文件且可以避免重复加载同一文件,尽量使用这个。


Lua中的函数定义时发生在运行时的赋值而不是编译时

loadfile:编译但不执行的理解用例

-- file `foo.lua'
function foo (x)
	print(x)
end
如果只执行f=loadfile("foo.lua"),则foo仅仅被编译,没有定义
f()				-- defines `foo'
foo("ok")		--> ok

loadstring:

调用loadstring时,只寻找全局变量做操作。对local变量无法找到




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值