Lua 101 - 基本语法

最近在重构我司项目,删掉那些又臭又长的代码,用精简的函数实现同样的功能心里巨爽,而且也没了历史包袱。一些新特性用着很嗨皮。不过也遇到了一些坑,其中有一段就是要调用 Lua 函数。然而 Lua 从未接触过。先瞅瞅基本语法。

Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

Lua 特性

  • 轻量级: 它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。
  • 可扩展: Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
  • 支持面向过程(procedure-oriented)编程和函数式编程(functional programming)
  • 自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象
  • 语言内置模式匹配;闭包(closure);函数也可以看做一个值;提供多线程(协同进程,并非操作系统所支持的线程)支持
  • 通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等。

配置环境

使用 Homebrew 安装 Lua 异常简单,只需要一行命令。

1
$ brew install lua

交互式编程

Lua 提供了交互式编程模式。我们可以在命令行中输入程序并立即查看效果。
Lua 交互式编程模式可以通过命令 lua -ilua 来启用:

1
2
3
$ lua
Lua 5.2.4 Copyright (C) 1994-2015 Lua.org, PUC-Rio
>

脚本式编程

我们可以将 Lua 程序代码保持到一个以 lua 结尾的文件,并执行,该模式称为脚本式编程,如我们将如下代码存储在名为 hello.lua 的脚本文件中:

1
print("Hello World!")

使用 lua 执行以上脚本,输出结果为

1
2
$ lua hello.lua
Hello World!

基本语法

使用 Lua 输出”Hello World!”

1
2
> print("Hello World!")
Hello World!

注释

1
2
3
4
5
6
-- 两个减号为单行注释
--[[
多行注释
多行注释
--]]

标识符

Lua 表示符用于定义一个变量,函数获取其他用户定义的项。标示符以一个字母 A 到 Z 或 a 到 z 或下划线 _ 开头后加上0个或多个字母,下划线,数字(0到9)。

变量

数据类型

数据类型 描述
nil 这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
boolean 包含两个值:false和true。
number 表示双精度类型的实浮点数
string 字符串由一对双引号或单引号来表示
function 由 C 或 Lua 编写的函数
userdata 表示任意存储在变量中的C数据结构
thread 表示执行的独立线路,用于执行协同程序
table Lua 中的表(table)其实是一个”关联数组”(associative arrays),数组的索引可以是数字或者是字符串。在 Lua 里,table 的创建是通过”构造表达式”来完成,最简单构造表达式是{},用来创建一个空表。

所谓Table其实就是一个Key Value的数据结构,它很像Javascript中的Object,或是PHP中的数组,在别的语言里叫Dict或Map,Table长成这个样子:

1
brikerMan = {name="BrikerMan", age=18, handsome=True}

Lua 的数字只有 double 型,64bits,Lua 允许按照以下方式为数字赋值。

1
2
3
4
5
6
7
num = 1024
num = 3.0
num = 3.1416
num = 314.16e-2
num = 0.31416E1
num = 0xff
num = 0x56

字符串你可以用单引号,也可以用双引号,还支持C类型的转义,比如: ‘\a’ (响铃), ‘\b’ (退格), ‘\f’ (表单), ‘\n’ (换行), ‘\r’ (回车), ‘\t’ (横向制表), ‘\v’ (纵向制表), ‘\‘ (反斜杠), ‘\”‘ (双引号), 以及 ‘\” (单引号)
下面的四种方式定义了完全相同的字符串(其中的两个中括号可以用于定义有换行的字符串)

1
2
3
4
5
a = 'alo\n123"'
a = "alo\n123\""
a = '\97lo\10\04923"'
a = [[alo
123"]]

C语言中的NULL在Lua中是nil,比如你访问一个没有声明过的变量,就是nil,比如下面的n的值就是nil

1
2
> print(n)
nil

布尔类型只有nil和false是 false,数字0,’’空字符串(’\0’)都是true。

默认情况下,变量总是认为是全局的,那怕是语句块或是函数里。变量前加local关键字的是局部变量。

1
2
3
4
5
6
> print(n)
nil
> n = 1000
> print(n)
1000
>

如果你想删除一个全局变量,只需要将变量赋值为nil。

控制语句

while循环

1
2
3
4
5
6
7
sum = 0
num = 1
while num <= 100 do
sum = sum + num
num = num + 1
end
print("sum =",sum)

if else 分支

1
2
3
4
5
6
7
8
9
10
11
age = 10
if age == 40 and sex =="Male" then
print("男人四十一枝花")
elseif age > 60 and sex ~="Female" then
print("old man without country!")
elseif age < 20 then
io.write("too young, too naive!\n")
else
local age = io.read()
print("Your age is "..age)
end
  • “~=” 是不等于,而不是 !=
  • io 库的分别从 stdin 和 stdout 读写的 readwrite 函数
  • 字符串的拼接操作符”..”
  • 条件表达式中的与或非为分是:and, or, not关键字

for 循环

从 1 加到 100

1
2
3
4
sum = 0
for i = 1, 100 do
sum = sum + i
end

从 1 到 100 的奇数和

1
2
3
4
sum = 0
for i = 1, 100, 2 do
sum = sum + i
end

从100到1的偶数和

1
2
3
4
sum = 0
for i = 100, 1, -2 do
sum = sum + i
end

until 循环

1
2
3
4
5
sum = 2
repeat
sum = sum ^ 2 --幂操作
print(sum)
until sum >1000

函数

Lua 函数和 javascript 很像
递归

1
2
3
4
function fib(n)
if n < 2 then return 1 end
return fib(n - 2) + fib(n - 1)
end

1
2
3
4
5
6
7
8
9
10
11
12
13
14
--[[ 函数返回两个值的最大值 --]]
function max(num1, num2)
if (num1 > num2) then
result = num1;
else
result = num2;
end
return result;
end
-- 调用函数
print("两值比较最大值为 ",max(10,4)) --> 两值比较最大值为 10
print("两值比较最大值为 ",max(5,6)) --> 两值比较最大值为 6

Lua 中我们可以将函数作为参数传递给函数,如下实例:

1
2
3
4
5
6
7
8
9
10
11
12
myprint = function(param)
print("这是打印函数 - ##",param,"##")
end
function add(num1,num2,functionPrint)
result = num1 + num2
-- 调用传递的函数参数
functionPrint(result)
end
myprint(10)
-- myprint 函数作为参数传递
add(2,5,myprint)

函数的返回值

和Go语言一样,可以一条语句上赋多个值,如

1
name, age, bWoman = "BrikerMan", 18, false, "BrikerMan@gmail.com"

上面的代码中,因为只有3个变量,所以第四个值被丢弃。

函数也可以返回多个值:

1
2
3
4
5
6
function getUserInfo(id)
print(id)
return "BrikerMan", 18, "BrikerMan@hotmail.com", "eliyar.biz"
end
name, age, email, website, bWoman = getUserInfo()

注意:上面的示例中,因为没有传 id ,所以函数中的 id 输出为 nil,因为没有返回 bWoman,所以 bWoman 也是nil。

参考