《Lua程序设计》--学习2

这篇具有很好参考价值的文章主要介绍了《Lua程序设计》--学习2。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Lua语言中的本质上是一种辅助数组(associative array),这种数组不仅可以使用数值作为索引,也可以使用字符串或其他任意类型的值作为索引(nil除外)。

当调用函数math.sin时,我们可能认为是“调用了math库中函数sin”;而对于Lua语言来说,其实际含义是“以字符串"sin"为键检索表math”。

Lua语言中的表要么是值要么是变量,它们都是对象(object),表是一种动态分配的对象,程序只能操作指向表的引用(或指针)。除此以外,Lua语言不会进行隐藏的拷贝(hidden copies)或创建新的表

《Lua程序设计》--学习2

 对于一个表而言,当程序中不再有指向它的引用时,垃圾收集器会最终删除这个表并重用其占用的内存。

当语句 b  =  a,指的是b这个引用也指向了a指向的表,指向的是同一张表

表索引值

同一个表中存储的值可以具有不同的类型索引,并可以按需增长以容纳新的元素

将nil赋值给表元素可以将其删除,Lua语言实际上就是使用表来存储全局变量的

当把表当作结构体使用时,可以把索引当作成员名称使用

《Lua程序设计》--学习2

 a.x代表的是a["x"],即由字符串"x"索引的表;而a[x]则是指由变量x对应的值索引的表

《Lua程序设计》--学习2

2和2.0的值相等,所以当它们被当作表索引使用时指向的是同一个表元素,当被用作表索引时,任何能够被转换为整型的浮点数都会被转换成整型数

《Lua程序设计》--学习2

表构造器

表构造器(Table Constructor)是用来创建和初始化表的表达式

《Lua程序设计》--学习2

《Lua程序设计》--学习2

在同一个构造器中,可以混用记录式(record-style)和列表式(list-style)写法

《Lua程序设计》--学习2

 《Lua程序设计》--学习2

 通过方括号括起来的表达式显式的指定每一个索引

《Lua程序设计》--学习2

《Lua程序设计》--学习2

 数组,列表和序列

如果想表示常见的数组(array)或列表(list),那么只需要使用整型作为索引的表即可

我们把这种所有元素都不为nil的数组称为序列(sequence),也就是整个数组是全部有效的,没有空洞,可以将末尾设置成nil来标记数组的长度

在Lua语言中,数组索引按照惯例是从1开始的(不像C语言从0开始),Lua语言中的其他很多机制也遵循这个惯例。

操作符 # 也可以用于表,返回表对应的序列的长度

《Lua程序设计》--学习2

 对于中间存在空洞(nil值)的列表而言,序列长度操作时不可靠的

不包含数值类型的键的表就是长度为零的序列

我们把所有元素都不为nil的数组称为序列(sequence)

《Lua程序设计》--学习2

对于Lua语言而言,一个为nil的字段和一个不存在的元素没有区别。因此,上述列表与{10,20,30}是等价的——其长度是3,而不是5。

遍历表

《Lua程序设计》--学习2

 pairs 顺序是随机的,保证每个元素出现一次

《Lua程序设计》--学习2

 ipairs 遍历,保证按顺序遍历

《Lua程序设计》--学习2

 使用数值型for循环

安全访问

《Lua程序设计》--学习2

 对表进行了6次访问,改写成下面这样

对于这种情景,诸如C#的一些编程语言提供了一种安全访问操作符(safe navigation operator)。在C#中,这种安全访问操作符被记为“?.”。例如,对于表达式a?.b,当a为nil时,其结果是nil而不会产生异常。使用这种操作符,可以将上例改写为: 

《Lua程序设计》--学习2 

Lua语言并没有提供安全访问操作符, 不过,我们可以使用其他语句在Lua语言中模拟安全访问操作符。对于表达式a or{},当a为nil时其结果是一个空表。因此,对于表达式(a or{}).b,当a为nil时其结果也同样是nil。这样,我们就可以将之前的例子重写为:

《Lua程序设计》--学习2

进一步简化: 

《Lua程序设计》--学习2

于表达式a or{},当a为nil时其结果是一个空表

表中的每个字段名都只是用了一次,从而保证了尽可能少的对表进行访问,本例中访问了三次,同时避免了引入新的操作符

表标准函数

函数table.insert向序列的指定位置插入一个元素,其他元素依次后移

 对于列表t={10,20,30},在调用table.insert(t,1,15)后它会变成{15,10,20,30}

调用时不指定位置的话会直接插在末尾不移动任何元素

 函数table.remove删除并返回序列指定位置的元素,然后将其后的元素向前移动填充删除元素后造成的空洞。如果在调用该函数时不指定位置,该函数会删除序列的最后一个元素

函数table.move(a,f,e,t),调用该函数可以将表a中从索引f到e的元素(包含索引f和索引e对应的元素本身)移动到位置t上,这样就可以空出第一个元素的位置,方便模拟栈

《Lua程序设计》--学习2

练习题:

sunday = "monday";monday = "sunday"
t = {sunday = "monday",[sunday] = monday}
 -- => t = { ["sunday"] = "monday" , ["monday"] = "sunday" }
print(t.sunday,t[sunday],t[t.sunday])    
 -- => print(t["sunday"],t["monday"],t["monday"])
--monday sunday sunday

函数

在Lua语言中,函数(Function)是对语句和表达式进行抽象的主要方式。函数既可以用于完成某种特定任务(有时在其他语言中也称为过程(procedure)或子例程(subroutine)),也可以只是进行一些计算然后返回计算结果

当函数只有一个参数且该参数是字符串常量或表构造器时,括号是可选的:

《Lua程序设计》--学习2

 Lua语言也为面向对象风格的调用(object-oriented call)提供了一种特殊的语法,即冒号操作符。形如o:foo(x)的表达式意为调用对象o的foo方法

一个Lua程序既可以调用Lua语言编写的函数,也可以调用C语言(或者宿主程序使用的其他任意语言)编写的函数

调用函数时使用的参数个数可以与定义函数时使用的参数个数不一致。Lua语言会通过抛弃多余参数和将不足的参数设为nil的方式来调整参数的个数。

《Lua程序设计》--学习2

多返回值

使用多重赋值(multipleassignment)可以同时获取到这两个结果:

《Lua程序设计》--学习2

请记住,字符串的第一个字符的索引值为1。 

 Lua语言编写的函数同样可以返回多个结果,只需在return关键字后列出所有要返回的值即可

Lua语言根据函数的被调用情况调整返回值的数量。当函数被作为一条单独语句调用时,其所有返回值都会被丢弃;当函数被作为表达式(例如,加法的操作数)调用时,将只保留函数的第一个返回值。只有当函数调用是一系列表达式中的最后一个表达式(或是唯一一个表达式)时,其所有的返回值才能被获取到

在多重赋值中,如果一个函数调用是一系列表达式中的最后(或者是唯一)一个表达式,则该函数调用将产生尽可能多的返回值以匹配待赋值变量,否则只返回一个结果

《Lua程序设计》--学习2

《Lua程序设计》--学习2 

 当一个函数调用是另一个函数调用的最后一个(或者是唯一)实参时,第一个函数的所有返回值都会被作为实参传给第二个函数。我们已经见到过很多这样的代码结构,例如函数print。由于函数print能够接收可变数量的参数,所以print(g())会打印出g返回的所有结果。

《Lua程序设计》--学习2

当我们调用f(g())时,如果f的参数是固定的,那么Lua语言会把g返回值的个数调整成与f的参数个数一致。这并非巧合,实际上这正是多重赋值的逻辑。 

 表构造器会完整地接收函数调用的所有返回值,而不会调整返回值的个数

《Lua程序设计》--学习2

 不过,这种行为只有当函数调用是表达式列表中的最后一个时才有效,在其他位置上的函数调用总是只返回一个结果

《Lua程序设计》--学习2

将函数调用用一对圆括号括起来可以强制其只返回一个结果

《Lua程序设计》--学习2

 可变长参数函数

Lua语言中的函数可以是可变长参数函数(variadic),即可以支持数量可变的参数

我们将三个点组成的表达式称为可变长参数表达式(vararg expression)

《Lua程序设计》--学习2

 具有可变长参数的函数也可以具有任意数量的固定参数,但固定参数必须放在变长参数之前。Lua语言会先将前面的参数赋给固定参数,然后将剩余的参数(如果有)作为可变长参数。

样。不过,在某些罕见的情况下,如果可变长参数中包含无效的nil,那么{...}获得的表可能不再是一个有效的序列。此时,就没有办法在表中判断原始参数究竟是不是以nil结尾的。对于这种情况,Lua语言提供了函数table.pack。该函数像表达式{...}一样保存所有的参数,然后将其放在一个表中返回,但是这个表还有一个保存了参数个数的额外字段"n"

《Lua程序设计》--学习2

 另一种遍历函数的可变长参数的方法是使用函数select。函数select总是具有一个固定的参数selector,以及数量可变的参数。如果selector是数值n,那么函数select则返回第n个参数后的所有参数;否则,selector应该是字符串"#",以便函数select返回额外参数的总数。

《Lua程序设计》--学习2

 函数table.unpack

该函数的参数是一个数组,返回值为数组内的所有元素:

《Lua程序设计》--学习2

 函数table.unpack与函数table.pack的功能相反。pack把参数列表转换成Lua语言中一个真实的列表(一个表),而unpack则把Lua语言中的真实的列表(一个表)转换成一组返回值,进而可以作为另一个函数的参数被使用。

如果我们想通过数组a传入可变的参数来调用函数f,那么可以写成:

《Lua程序设计》--学习2

正确的尾调用

Lua语言是支持尾调用消除(tail-call elimination)的。这意味着Lua语言可以正确地(properly)尾递归(tail recursive)

尾调用(tail call)是被当作函数调用使用的跳转。当一个函数的最后一个动作是调用另一个函数而没有再进行其他工作时,就形成了尾调用

《Lua程序设计》--学习2

当函数f调用完函数g之后,f不再需要进行其他的工作。这样,当被调用的函数执行结束后,程序就不再需要返回最初的调用者。因此,在尾调用之后,程序也就不需要在调用栈中保存有关调用函数的任何信息。当g返回时,程序的执行路径会直接返回到调用f的位置。使得在进行尾调用时不使用任何额外的栈空间。我们就将这种实现称为尾调用消除(tail-call elimination)

由于尾调用不会使用栈空间,所以一个程序中能够嵌套的尾调用的数量是无限的。例如,下列函数支持任意的数字作为参数

《Lua程序设计》--学习2

该函数永远不会栈溢出

很多函数调用之所以不是尾调用,是由于这些函数在调用之后还进行了其他工作。例如,下例中调用g就不是尾调用:

《Lua程序设计》--学习2

 这个示例的问题在于,当调用完g后,f在返回前还不得不丢弃g返回的所有结果。类似的,以下的所有调用也都不符合尾调用的定义:

《Lua程序设计》--学习2

 在Lua语言中,只有形如returnfunc(args)的调用才是尾调用。不过,由于Lua语言会在调用前对func及其参数求值,所以func及其参数都可以是复杂的表达式。例如,下面的例子就是尾调用:

《Lua程序设计》--学习2文章来源地址https://www.toymoban.com/news/detail-479188.html

--print(returnWithoutFirst(1,2,3,4,5))

---练习6.3 请编写一个函数,该函数的参数为可变数量的一组值,返回除最后元素之外的其他所有值
local function returnWithoutLast(...)
   local t = table.pack(...)
   table.remove(t)
   return table.unpack(t)
end

--print(returnWithoutLast(1,2,3,4,5))

到了这里,关于《Lua程序设计》--学习2的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《Lua程序设计第四版》 第一部分自做练习题答案

    Lua程序设计第四版第一部分语言基础自做练习题答案,带⭐为重点。 运行阶乘的示例并观察,如果输入负数,程序会出现什么问题?试着修改代码来解决问题 输入负数,程序会死循环,修改如下 分别使用-l参数和dofile运行twice示例,并感受你喜欢哪种方式 载入库,在 lua解释

    2024年02月13日
    浏览(53)
  • 《Lua程序设计第四版》 第二部分14~17章自做练习题答案

    Lua程序设计第四版第二部分编程实操自做练习题答案,带⭐为重点。 该函数用于两个稀疏矩阵相加 改写队列的实现,使得当队列为空时两个索引都返回0 修改图所用的数据结构,使得图可以保存每条边的标签。该数据结构应该使用包括两个字段的对象来表示每一条边,即边的

    2024年02月13日
    浏览(49)
  • 《Lua程序设计第四版》 第二部分9~13章自做练习题答案

    Lua程序设计第四版第二部分编程实操自做练习题答案,带⭐为重点。 请编写一个函数integral,该函数以一个函数f为参数并返回其积分的近似值 使用右矩阵法近似积分值 如下代码段将输出什么结果 编写练习5.4的柯里化版本 柯里化(Currying)是把接受 多个参数 的函数变换成

    2024年02月13日
    浏览(88)
  • 《Lua程序设计第四版》 第一部分前8章自做练习题答案

    Lua程序设计第四版第一部分语言基础自做练习题答案,带⭐为重点。 运行阶乘的示例并观察,如果输入负数,程序会出现什么问题?试着修改代码来解决问题 输入负数,程序会死循环,修改如下 分别使用-l参数和dofile运行twice示例,并感受你喜欢哪种方式 载入库,在 lua解释

    2024年02月13日
    浏览(162)
  • 【软件设计师07】程序设计语言与语言处理程序基础

    编译与解释、文法、正规式、有限自动机、表达式、传值与传址、多中程序语言特点 (逐渐降低考察比例,很少考察) 概念 文法类型 语法推导树 有限自动机 与正规式(重点) 常见问题:给一个串比如01、10、001等,看图中起点到终点能否连起来得到这样的串 正规式 是有限自

    2023年04月08日
    浏览(62)
  • Java语言程序设计课程设计

    Java语言程序设计课程设计 一、 java语言程序设计课程设计要求: (1)java语言课程设计软件设计要求 1.题目不做严格限定,可自行选择题目来完成。 2.模块化程序设计 3.锯齿型书写格式 4.必须上机调试通过 (2)撰写课程设计报告,内容包括: 1.课程设计题目; 2.需求分析;

    2024年02月08日
    浏览(46)
  • 【高级程序设计语言C++】特殊类设计

    拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 用C++11的话,可以使用特殊的语法来实现一个不能被拷贝的类。在C++11中,可以使用删除函数(deleted function)来禁用拷

    2024年02月10日
    浏览(51)
  • C语言程序设计——设计一个学生管理系统(完美运行的程序(●‘◡‘●))

    通过c语言设计一个学生管理系统,要求有直观的主菜单,可以录入学生的信息,实现添加学生信息、显示学生信息、查找学生信息、删除学生信息、修改学生信息以及退出等功能。 1、首先因为学生有以下几个基本信息:姓名、年龄、学号、性别,依次由name、age、id和sex来表

    2024年02月08日
    浏览(48)
  • 南京邮电大学汇编语言程序设计实验二(用户登录验证程序的设计)

    1.掌握循环程序的编写以及结束循环的方法。 2.掌握DOS、BIOS功能调用的使用方法。 用户登录验证程序的实现 程序执行后,给出提示操作,请用户键入用户名和密码;用户在键入密码时,程序不回显键入字符;只有当用户键入的用户名,密码字符串和程序内定的字符串相同时

    2023年04月18日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包