Lua_Basics
Posted 程序员不是码农
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lua_Basics相关的知识,希望对你有一定的参考价值。
最近看学习skynet框架,skynet中一般采用Lua来实现业务逻辑,也可用Lua来实现一些服务。因此准备学习一下Lua这门脚本语言,挑了《Programming in Lua》这本开始啃了起来(英文原版)。并将一些值得mark的知识点总结记录了下来,一来加深理解,二来便于后续温故知新。不得不说这本书真的很赞,入门看它就够了,遇到一些不懂的接口,勤于查Lua官方文档。因此主要学习资料也就是一本书+官方文档即可。
Lua的一些特点
Lua作为一门简单(Simplicity),可扩展(Extensibility),可移植(Portability),以及高效(Efficiency)的脚本语言,被应用在各个领域。(Lua是脚本语言中效率最高的)
Lua是一门动态语言:变量没有类型,变量的值才有类型。
Lua是一门解释性语言:生成字节码交由Lua虚拟机进行处理。(Python也是如此)
Lua一共有8中基本类型
nil:任何全局变量在赋值前默认都是nil,可通过将一个变量赋值为nil来删除它
boolean: lua中只有false和nil为false,其他的都是true(包括0)
number: 包括整数和浮点数 注意0 == 0.0(true)
string:Lua中的string是不可变的(immutable)
userdata(内存块): 分为完全用户数据(由lua创建的内存并由lua进行gc)和轻量用户数据(由c/c++创建的内存,由c/c++释放)
function: Lua中到处都是函数,一个lua文件都可认为是一个匿名function
table: Lua中唯一也是最重要的数据结构
thread
Exercise
介绍一个计算阶乘的例子
numbers内容比较简单,直接从string开始。
Lua中字符串是不可变的(immutable),我们不能改变字符串中的字符,一般会创建一个新的字符串来达到修改的目的,如下:
string.gsub用法总结
原型:string.gsub(s, pattern, repl[,n])
功能:拷贝一份字符串s,并将s中出现的所有(或者n次,如果有)pattern替换成repl,返回两个参数,第一个为替换过后的字符串,第二个为替换字符串的次数。repl可为三种类型:string,table,function.
repl为string
1. 为普通string,直接替换,如上string.gsub(s, "one", "another")
2. %d形式,d可以为0-9,0代表整个匹配的字符串,否则代表第d个匹配的字符串
repl为table
会将匹配到的字符串作为key,根据key从table中取出value,再进行替换
repl为function
将匹配到字符串作为参数传递给function,并将function执行的返回结果进行替换
长字符串表示
两种方式,第一种使用[=[ ... ]=]
, 第二种使用
进行换行,如下
字符串拼接(concatenation)
使用..
进行拼接,拼接不会改变原有字符串(也不能改变,上述提到lua中string是不可变的)。
但是这种拼接方式是低效的,如果同时需要拼接多个字符串的话,因为每次拼接就意味着一次内存分配和字符串拷贝(其他脚本语言如python也同样有类似问题)。应当使用更为高效的字符串拼接方式table.concat,无论多少字符串,都只需要进行一次内存分配,每个带拼接的字符串也只需要拷贝一次。
string标准库
Lua的字符串库提供了丰富的函数,比如string.len, string.rep, string.reverse, string.lower, string.upper
等,常用的字符串操作应该都可以满足,这里就不展开,在处理字符串的时候可以先看下Lib中是否已经实现了我们想要的功能,避免重复造轮子。
Exercise
1. 编写函数,实现在某个字符串的指定位置插入另外一个字符串
2. 编写函数,移除字符串中的指定部分(由起始位置和长度指定)
3. 判断是不是回文字符串,需要忽略空格和标点符号
Table是Lua中唯一的数据结构,但是Table非常灵活,基于Table可以实现其他编程语言中的所有数据结构,比如数组、集合、队列、栈等,甚至可以用Table来实现类。
除了nil,Table可以用任何类型作为key。
通过将Table中的key对应的value赋值为nil来删除Table中的key
可以通过下标
[]
或者.
来访问Table中的元素,比如a[x]
和a.x
注意这两个代表的含义不同,前者变量x为key,后者字符串"x"作为key。Table中第一个元素的下标从1开始
Table的创建很灵活,主要有两种方式,一种是list-style, 一种是record-style,比如:
使用Table实现列表时,我们把不包含nil的列表称为序列(sequence),只有序列用
#
来获取Table的长度才是准确的。我们可以利用#
来向序列末尾插入一个元素,a[#a + 1] = v
;如果不是序列,我们可以通过遍历table的方式计算table长度。
Table的三种遍历方式
如何高效访问嵌套Table
TODO
深入学习Table,需要搞懂以下问题
Lua源码中Table底层数据结构的实现(数组和哈希表),以及如何扩容,进而懂得如何使用table写出高效代码。
元表如何来使用,
__index
与__newindex
,rawget
与rawset
这些进阶知识点后续会结合源码深入讲解。
Exercise
下列代码输出什么?(可帮助我们理解t.a和t[a]问题)
编写函数,测试table是否为有效序列
table标准库提供了函数table.concat用于连接表中字符串;请实现自己的concat对比和table.concat的性能
Lua中到处都是函数,甚至main.lua
这种文件中的代码都可以看做是一个匿名函数。
可变参数函数
可以使用三个点...
来表示可变参数
尾调用
尾调用不会保存调用函数的信息在栈上,比如:
Exercise
主要介绍IO模块,以及其他一些外部库,了解io.read
, io.write
, io.input
, io.output
, io.popen
, os.execute
等一些接口。
io的默认输入为stdin
,默认输出为stdout
,通过使用io.input
和io.output
可以设置其输入输出方式。
本文主要介绍Lua中的几种重要类型,并通过一些实例来帮助理解这些类型结构,在阅读《Programming In Lua》时,一定要把课后题撸一遍,学习效果会更加明显。
参考:
http://www.lua.org/pil/
http://www.lua.org/manual/5.3/manual.html#lua_call
以上是关于Lua_Basics的主要内容,如果未能解决你的问题,请参考以下文章