<p>Lua 是一门强大、快速、轻量的嵌入式脚本语言,那么我们如何才能够快速学习和掌握 Lua 语言呢?在这我将分享一下我的 Lua 快速入门经验,希望对大家有所帮助。</p>

Lua 的安装过程可以参考 Lua 官网 或云风翻译的 Lua 5.3 参考手册

在 Mac OS 上安装

  1. 从 Lua 官网下载 Lua 最新的源码,然后解压。
  2. 打开终端,并 cd 到解压后的 Lua 源码目录 lua-5.3.2/
  3. 在终端中输入 make macosx install 构建并安装 Lua。
  4. 在终端中输入 lua -v 查看 Lua 是否已经安装完成。

PS:如果你没有安装 Xcode 和命令行工具是不能使用 make 命令的。

在 Windows 上安装

下载 luaforwindows 并安装,这样 lua 的开发环境就搭建好了,安装后可以直接使用 SciTE IDE 来进行 lua 代码的编写和运行。

Lua 编辑器的选择

在这里介绍一下怎么使用 Sublime Text 来编写和运行 Lua 代码,当然你也可以使用其他文本编辑器或者 IDE 来编写和运行 Lua 代码,例如在 Windows 上你可以直接使用上面所说的 SciTE。

  1. 下载并安装 Sublime Text

  2. 打开 Sublime Text,点击菜单栏中的 Tools -> Build System -> New Build System。在新建的 untitled.sublime-build 文档中输入以下代码,并把其中的 /usr/local/bin/lua 修改为你安装 Lua 后可执行文档 lua 的路径(终端 lua 命令其实执行的也是这个文档,在 Mac OS 系统上为 /usr/local/bin/lua)。最后 ctrl + s 将文档保存为 lua.sublime-build,保存位置默认即可。你可以在 /Users/gui/Library/Application Support/Sublime Text 2/Packages/User/ 目录下找个你保存的 lua.sublime-build 文档。

    1
    2
    3
    4
    5
    {
    "cmd":["/usr/local/bin/lua", "$file"],
    "file_regex":"^(...*?):([0-9]*):?([0-9]*)",
    "selector":"source.lua"
    }
  3. 在 Sublime Text 中新建一个文档,输入 print("hello world") 并保存为 test.lua,然后 ctrl + b 运行,这个时候我们就能在 Sublime Text 中的控制面板看到输出 “hello world”。

Lua 快速入门资料

  1. Lua 官方参考手册 或云风翻译的 Lua 5.3 参考手册
  2. 书籍《Lua 进程设计》。

Lua 参考手册非常适合作为快速入门的阅读资料,对 Lua 的语法等有疑惑时查看 Lua 参考手册也能快速解惑。《Lua 进程设计》除了介绍 Lua 的语法等基础知识外,还会介绍一些 Lua 高级的用法,例如:面向对象编程(在 Lua 中怎么实现类、继承、多重继承等),所以《Lua 进程设计》也是非常值得去购买的一本书籍。

PS:在学习的过程中,建议对于不理解和有疑惑的地方参照资料自己动手编写代码并运行查看输出结果。

Lua 语法

这里主要简单介绍一下 Lua 的语法和在使用过程中特别需要注意事项,同时对 Lua 和其他一些编程语言很不一样的地方进行说明。以下的部分内容引用自:云风翻译的 Lua 5.3 参考手册 和《Lua 进程设计》。

打印

print (···)

接收任意数量的参数,并将它们的值打印到 stdout。 它用 tostring 函数将每个参数都转换为字符串。 print 不用于做格式化输出。仅作为看一下某个值的快捷方式。 多用于调试。 完整的对输出的控制,请使用 string.format 以及 io.write。

注释

Lua 中使用 -- 作为行注释,使用 --[[]] 作为块注释。

块注释的常见写法如下,这样只需要在块注释的最前面加上 “-” 即可取消整个块注释,非常实用的一个小技巧。

1
2
3
4
5
块注释常见技巧:只要在块注释的前面加上“-”即可取消注释
--]]

值和类型

Lua 中有八种基本类型:nilbooleannumberstringfunctionuserdata
threadtable

nil 和 false 都会导致条件判断为假;而其它任何值都表示为真。

表、函数、线程、以及完全用户数据在 Lua 中被称为 对象:变量并不真的 持有 它们的值,而仅保存了对这些对象的 引用。赋值、参数传递、函数返回,都是针对引用而不是针对值的操作,这些操作均不会做任何形式的隐式拷贝。

Lua 是一门动态类型语言。这意味着变量没有类型;只有值才有类型。语言中不设类型定义。所有的值携带自己的类型。

Lua 中所有的值都是 一等公民。这意味着所有的值均可保存在变量中、当作参数传递给其它函数、以及作为返回值。

Lua 中,函数可以保存在变量中、当作参数传递给其它函数、以及作为返回值。

局部变量和全局变量

所有没有显式声明为局部变量的变量名都被当做全局变量。在编写 Lua 代码的时候如果不是全局变量一定记得添加 local。

1
2
b = 2
local a = 1 -- 局部变量 a

字符串

Lua 中字符串通常使用单引号或者双引号来界定,但在某些特殊的情况下会用一对匹配的双方括号来界定一个字母字符串,就像写“块注释”那样。这种写法对于书写那种含有进程代码的字符串尤为有用。如果第一个字符是换行符,那么lua会忽略它。

在两个方括号间加上任意数量的等号,这样字符串或者注释只有遇到一个内嵌有相同数量定好的双右方括号时才会结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
page = [=[
<html>
<head>
<title>An html page</title>
</head>
<body>
<a href="http://www.lua.org">Lua</a>
</body>
<html>
--[[
a = "one string"
b = string.gsub(a, "one", "another")
print("a =", a)
print("b =", b)
--]]
]=]
print("-- print page string -- ")
print(page)

输出结果如下图:

ipairs 和 pairs

  1. ipairs 将迭代表中的键值对(1,t[1]) ,(2,t[2]), … ,直到第一个空值。注意:是从 1 开始迭代,而不是从 0 开始迭代。
  2. pairs 能迭代表中的所有键值对,而且迭代的顺序是不保证的,每次执行迭代的顺序都可能不一样。

ipairs 通常只用于迭代序列,而 pairs 则可用于迭代所有的表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
local t = {}
t[0] = 0
t[1] = 1
t[2] = 2
t[4] = 4
t["x"] = "x"
t["y"] = "y"
print("------ ipairs ------")
for i,v in ipairs(t) do
print(i,v)
end
print("------ pairs ------")
for k,v in pairs(t) do
print(k,v)
end

输出如下图:

唯一的数据结构 table

表是 Lua 中唯一的数据结构,它可被用于表示普通数组、序列、符号表、集合、记录、图、树等等。对于记录,Lua 使用域名作为索引。语言提供了 a.name 这样的语法糖来替代a["name"] 这种写法以方便记录这种结构的使用。

table 构造式

  1. 列表风格构造式:{”r“, "g", "b"}
  2. 记录风格构造式:{x = 10, y = 20}
  3. 通用风格构造式:{[1] = "r", [2] = "g", [3] = "r"} {["x"] = 10, ["y"] = 20}

函数

当函数只有一个参数并且该参数是一个字符串或者 table 时,函数调用时的括号是可以省略的。

1
2
3
4
5
6
7
8
9
function (t)
print(table.concat(t, ","))
end
f{1, 2, 3}
print "Hello World" --> print("Hello World")
print [=[a multi-line
message]=]
print(type{})

取长度操作符

如果 __len 元方法没有给出,表 t 的长度只在表是一个 序列 时有定义。序列指表的正数键集等于 {1..n} ,其中 n 是一个非负整数。在这种情况下,n 是表的长度。注意这样的表 {10, 20, nil, 40} 不是一个序列,因为它有键 4却没有键 3,因此,该表的正整数键集不等于 {1..n} 集合,故而就不存在 n。注意:一张表是否是一个序列和它的非数字键无关。

取长度操作符对于不是序列(有时也称为数组、线性表)的 table 来说是无意义的。

从下面的代码的输出很明显可以看出:当 table 不是序列的时候,取长度操作符的结果是变动的、无意义的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
-- #取长度操作符,table的长度是从1算起
local t1 = {}
t1[1] = 1
t1[2] = 2
print("t1", #t1) --> 2
-- #取长度操作符,返回一个数组或线性表的最后一个索引值。
-- #取长度操作符对于不是数组或者线性表的table来说是无意义的。
local t2 = {}
t2[1] = 1
t2[2] = 2
t2[4] = 4
print("t2", #t2) --> 4
local t3 = {}
t3[1] = 1
t3[2] = 2
t3[5] = 5
print("t3", #t3) --> 2
local t4 = {}
t4[1] = 1
t4[2] = 2
t4[1000] = 1000
print("t4", #t4) --> 2
local t5 = {}
t5[1] = 1
t5[2] = 2
t5[3] = 3
t5[4] = 4
t5[7] = 7
t5[1000] = 1000
print("t5", #t5) --> 4
local t6 = {}
t6[1] = 1
t6[2] = 2
t6[3] = 3
t6[4] = 4
t6[7] = 7
t6[8] = 8
t6[1000] = 1000
print("t6", #t6) --> 8

字符串连接符

在 Lua 中,连接两个字符串或者连接字符串和一个其他值使用字符串连接符 ..。在使用过程中应该在字符串连接符前面和后面都添加一个空格,例如:"str" .. 666。特别当其中一个值是 number 时,如果写成 "str"..666666.."str" 这样,运行时就会出错:unexpected symbol near '..'。因为字符串连接符和数字之间没有空格,Lua 就无法区分这是小数点还是字符串连接符了。所以在使用字符串连接符的时候,不要为了方便而省略空格。