Lua_Real_Programming

Posted 程序员不是码农

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lua_Real_Programming相关的知识,希望对你有一定的参考价值。

《Programming in Lua的第二部分,主要介绍Lua中的闭包,模式匹配,日期时间表示,数据结构实现,编译执行和错误方式,以及模块(Modules)和包(Packages)的概念。


1
Closures(闭包)


Lua的函数function属于first-class的值, 也就是function同Lua中的其他类型number、string、table等所处的地位一样,function也可作为一个变量存储在table中。

那么如何理解function是为first-class呢?以下通过两种函数申明方式来进行解释

这两种声明方式都是申明一个foo的函数,实现2 * x的功能。

第2种申明可如此理解:右侧函数定义作为一条申明语句,创建一个类型为function的值,并把它赋予foo这个变量。甚至,可以理解在Lua中所有的函数都是匿名的,我们平常用到的函数比如print,只不过是把print作为一个变量保存了对应的函数而已。


使用table.sort来举例说明匿名函数的便利性,根据如下network中name这种字段的字母逆序进行排序

Lua_Real_Programming


函数声明方式

Lua_Real_Programming

对于局部函数,需要注意递归的情况,如下申明会出现函数未定义情况。

Lua_Real_Programming


闭包

先看如下例子:

Lua_Real_Programming

以上就是一个闭包,newCounter返回一个匿名函数,而这个匿名函数用到了newCounter中定义的local变量count,这个count就是所谓的上值(up-value),每次调用这个返回的匿名函数比如c1(),这个count貌似已经不在作用域内了,因为newCounter已经返回了,于是,Lua中采用闭包来处理和解决这种情况,每一次的调用,这个count的值会加一并保存。当创建一个新的匿名函数比如c2,c2的count跟c1拥有的count是完全分开独立,互不干扰的,也就是说c2产生了一个新的闭包。因此c1和c2是基于同一个匿名函数的不同闭包


闭包让Lua函数的功能变得更强大,以下是使用闭包的例子:

Lua_Real_Programming



2
Pattern Matching(模式匹配)



Lua模式匹配的实现代码不到600行,没有实现所有POSIX正则表达式的全部功能,但是Lua模式匹配功能强大,提供了很多feature是在标准的POSIX中很难做到的。



模式匹配相关函数

string.gsub, 这个接口之前已有介绍,不再赘述。


string.find

string.find (s, pattern [, init [, plain]])


寻找字符串s中pattern匹配的位置,匹配成功则返回两个索引值(pattern的起始和终止位置),否则返回nil。

Lua_Real_Programming


第三个可选参数init表明从哪里开始搜索,其默认值是1


第四个可选参数plain表明是否为普通的字符串子串的搜索,不考虑模式匹配,如下:

Lua_Real_Programming


string.match

string.match (s, pattern [, init])

string.find类似,但是其不是返回成功匹配的位置,而是返回成功匹配的内容,第三个默认参数init同样为指定搜索起点。例子如下:

Lua_Real_Programming


string.gmatch

string.gmatch(s, pattern)

返回一个迭代器函数,遍历字符串中所有出现的pattern。

Lua_Real_Programming


Patterns模式

Lua中使用%来作为转义字符,常用字符含义如下

Lua_Real_Programming


所有转义字符的大写,表示其补集,例如%A代表所有的非字母字符(%a为所有字符),如:

Lua_Real_Programming


在Lua的模式中有一些字符具有特殊含义,被称为Magic Characters, 如下:

Lua_Real_Programming


Lua提供了4种修改器如下:

Lua_Real_Programming

Lua_Real_Programming


Exercise

请编写一个函数split,该函数接受两个参数,第一个参数是字符串,第二个参数是分隔符模式:

Lua_Real_Programming


3
Date and Time (日期和时间)



Lua中日期和时间有两种表示方式:一种是整数形式,一种是table形式(日期table有以下这些域:year, month, day, hour, min, sec, way, yay, and isdst)。


os.time

Lua_Real_Programming


os.date

其功能跟os.time相反,是将数字表示的时间和日期转换成date table或者字符串等更加易读的形式。

Lua_Real_Programming

例如:

Lua_Real_Programming


Date-Time操作

计算从此刻起40天以后那天的日期

Lua_Real_Programming


4
Data Structures(数据结构)



Lua可以用table高效的实现数组,列表,队列,集合等数据结构。


Arrays数组

Lua_Real_Programming


Linked List列表

Lua_Real_Programming


Queue队列

Lua_Real_Programming


Sets集合

将元素作为key放入table中,value置为true即可

Lua_Real_Programming


String buffer字符串缓存

假定我们需要从文件中一行行读取数据,可以选用以下方法:

Lua_Real_Programming

这种方式效率极低,前面我们也提高过..进行字符串拼接是很低效的(一次拼接就是一个内存分配和字符移动)。因此可以选用更为高效的方式table.concat

Lua_Real_Programming


5
Compilation, Execution, and Errors



Compilation

loadfile从文件中加载Lua代码,只编译代码并将编译结果作为函数返回,dofile是基于loadfile,会执行函数,可定义如下:

Lua_Real_Programming

dofile更加完整,但是loadfile更加灵活,可只编译一次,运行多次,而dofile每次运行都需要编译,开销大。

loadloadfile功能类似,但是load不是从文件中读取Lua代码,而是从字符串或者函数中读取,如:

Lua_Real_Programming


在加载定义了函数的代码块时,有一个坑需要注意,lua中定义是需要通过赋值的:

Lua_Real_Programming

当使用loadfile加载上述两个文件时,加载foo1.lua后foo函数是没有被定义,需要执行之后才可使用,而foo2.lua被加载后foo可直接使用,如下:

Lua_Real_Programming


Errors

处理错误的方式:

Lua_Real_Programming

可以使用pcall在lua代码内部处理错误,不过使用pcall是看不到traceback的,因为其在返回错误代码时就已经销毁了调用栈。


6
Modules and Packages (模块和包)



模块:是能够通过函数require加载,然后返回一个table,任何模块导出的函数和常量,都定义在table中,这个table可以看作是一个命名空间。

Packages:由许多模块组成。

模块在lua中不是first-class,其不能作为参数传递给函数。

require加载模块时,会从package.path路径中去搜索,如果找到了对应文件,就通过loadfile进行加载。如果package.path中不能找对应的lua文件,就会从c库中去搜索,即package.cpath,如果在c库中找到了,就通过package.loadlib去找luaopen_modname的函数,其中modname为模块名称,luaopen_modname表示一个lua函数。


路径搜索

require搜索路径由一系列模版组成,模版之间用;隔开,如下;

Lua_Real_Programming

如果调用require sql,直接用sql替换上述路径中的?,那么其搜索顺序如下:

Lua_Real_Programming

以下为实现一个类似package.searchpath的例子

Lua_Real_Programming

首先要把modname中的.换成/,然后将modname替换path中的?


Lua中实现模块的方法

定义一个table,将所有函数放入table中,并返回table即可:

主要介绍Lua中闭包概念以及其用途,Lua的模式匹配,日期时间的两种表现形式以及相关转换接口,如何使用table实现其他数据结构如数组,列表,队列,集合等,实现,编译执行和错误方式,最后介绍了模块(Modules)和包(Packages)的概念。


参考:

http://www.lua.org/pil/

http://www.lua.org/manual/5.3/manual.html#lua_call

END



以上是关于Lua_Real_Programming的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段——CSS选择器

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

片段和活动之间的核心区别是啥?哪些代码可以写成片段?

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段6——CSS选择器

VSCode自定义代码片段——声明函数