简明Lua语法

Important

本教程推荐有其他编程语言基础的用户进行阅读,可以迅速掌握Lua语法
建议零基础、或看不懂这里的用户,点击左侧的白话Lua教程,查看零基础教程

词法约定

变量是以字母(letter)或者下划线开头的字母、下划线、数字序列。请不要使用下划线加大写字母的标示符,因为Lua的保留字也是这样的。

注意:Lua是大小写敏感的。 如and是保留字,但是And和AND则不是Lua的保留字。

一般在输入输入保留字的时候,会被编辑器自动高亮。

代码规范

  • 代码规范

Lua的多条语句之间并不要求任何分隔符,如C语言的分号(;),其中换行符也同样不能起到语句分隔的作用。因此下面的写法均是合法的。如:

a = 1
b = a * 2

a = 1;
b = a * 2;

a = 1; b = a * 2;
a = 1  b = a * 2
  • 注释

Lua代码中的注释分为2种:

一种是单行注释,如:

-- 单行注释


--[[

多行注释

--]]

变量

Lua变量分为全局变量和局部变量。

全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,全局变量在整个文件中起作用。访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil.

print(b)                                --> nil
b = 10
print(b)                                -->10
--如果你想删除一个全局变量,只需要将变量赋值为nil
b = nil
print(b)                                --> nil

局部变量通过local 来声明。与全局变量不同,局部变量只在被声明的那个代码块内有效。代码块:指一个控制结构内,一个函数体,或者一个chunk(变量被声明的那个文件或者文本串)。

local m = 9

if m <= 10 then
    local m = 5                     -- 这个局部变量m的作用范围是 then 和end 之间
print(m)
end
--运行结果是5.

local m = 9

if m <= 10 then
    print(m)                        -- 这个m是一开始声明的局部变量m
end
--运行结果是9.

另外Lua是动态类型语言,声明变量的时候不要类型定义。变量的类型和当前所赋值的类型是一致的。我们可以通过type函数获得变量的或值的类型信息,该类型信息将以字符串的形式返回。

local k = 1                         -- k是局部变量
print(type(k))                      --> number

k = "today is Friday"               -- 将一个字符串赋值给k
print(type(k))                      --> string

k = {1,2}                           -- 将一个表赋值给k
print(type(k))                      --> table

local d                             -- d 是局部变量,声明的时候未赋值
print(type(d))                      --> nil
d = 11                              -- d 后来被赋值
print(type(d))                      --> number

h = 9                               -- h是全局变量
print(type(h))                      --> number

值和类型

Lua中的值有8种类型:nil、boolean、number、string、userdata、function、thread和table。

  • nil型

Lua中特殊的类型,他只有一个值:nil,它的主要功能是由于区别其他任何值。一个全局变量没有被赋值以前默认值为nil;给全局变量负nil可以删除该变量。Lua将nil用于表示一种“无效值”的情况。

  • boolean型

该类型有两个可选值:false和true。但要注意Lua中所有的值都可以作为条件。在Lua中只有当值是false和nil时才视为“假”,其它值均视为真,如数字零和空字符串,这一点和C语言是不同的。

  • number型

表示实数。由于资源所限,如需使用浮点型数据,请使用文件名带有float的固件。

  • string型

指字符的序列。lua是8位字节,所以字符串可以包含任何数值字符,包括嵌入的0。这意味着你可以存储任意的二进制数据在一个字符串里。

m = "abc"
n = "\97\98\99"                 -- “a”的数值是97(decimal),”b”是98,”c”是99
print(m,n)                          --> abc  abc
print(“\09798”)                     --> a98

string和其他对象一样,Lua自动进行内存分配和释放,一个string可以只包含一个字母也可以包含一本 书,Lua可以高效的处理长字符串,1M的string在Lua中是很常见的。可以使用单引号或者双引号把一串字符括起来表示字符串:

a = "hello"
b = 'world'

为了风格统一,最好使用一种。例如一直使用双引号来表示字符串。如果双引号之间有单引号,系统会自动识别此单引号;如果双引号中之间还有双引号,则里面的双引号需要用转义字符\来区别: \

print("one line\nnext line\n\"in quotes\", 'in quotes'")
--[[
运行结果是:
one line
next line
"in quotes", 'in quotes'
]]

另外记住: Lua中的字符串是恒定不变的。String.sub函数以及Lua中其他的字符串操作函数都不会改变字符串的值,而是返回一个新的字符串。一个常见的错误是:string.sub(s, 2, -2)

认为上面的这个函数会改变字符串s的值。其实不会。如果你想修改一个字符串变量的值,你必须将变量赋给一个新的字符串:s = string.sub(s, 2, -2)

  • table型

table是Lua中唯一的数据结构,其他语言所提供的数据结构,如:数组、矩阵、链表、队列等,Lua都是通过table来很好地实现。

Lua中table的键(key)可以为任意类型(nil除外)。当通过整数下标访问table中元素时,即是数组。此外,table没有固定的大小,可以动态的添加任意数量的元素到一个table中

local t = {32,"jeep", name = "cherry"}
local p = {["name"] = "peach"}
print(t[1])                         --> 32
print(t[2])                         --> jeep
print(t["name"],t.name)         --> cherry  cherry
print(p["name"],p.name)         --> peach  peach
  • function型

函数是第一类值,意味着函数可以存储在变量中,可以作为函数的参数,也可以作为函数的返回值。这个特性给了语言很大的灵活性

  • userdata型

userdata可以将C数据存放在Lua变量中,userdata在Lua中除了赋值和相等比较外没有预定义的操userdata用来描述应用程序或者使用C实现的库创建的新类型。

表达式

Lua中的表达式包括数字、字符串、一元和二元操作符、函数调用。还可以是非传统的表构造。

  • 算数表达式

算数表达式是算数操作符及其操作对象所组成的表达式。Lua中算数操作符的操作对象是实数。

Lua中的算数操作符包括:

二元的算数操作符: +-*/^(指数)%(取模)

一元的算数操作符: -(负号)

    关系表达式

由关系操作符及其操作对象所组成的表达式就是关系表达式。所有关系表达式的结果均为true或false。

Lua支持的关系操作符有:>、<、>=、<=、==、~=。

有几点需注意:

==和~=这两个操作符可以应用于两个任意类型的值。

如果两个值的类型不同,Lua就认为他们不等。nil值与其自身相等。

print("0" == 0)                     -->false
print(nil == false)                 -->false
--特别地,tables、userdata、functions是通过引用进行比较的。也就是说,只有当他们引用同一个对象时,才视为相等。例如:

a = {x=1,y=2}
b = {x=1,y=2}
c = a
print(a==c)                     -->true
print(b==c)                     -->false

Lua比较数字按传统的数字大小进行,比较字符串按字母的顺序进行,但是字母顺序依赖于本地环境。

print( 3 < 25)                      -->true
print( “3” <"25")                   -->false (alphabetical order!)

把字符串或数字用>、<、>=、<=符与不同类型的值比较时,会报错。

print( 3 <“25”)                     --> attempt to compare number with string
print(5>=false)                 -->attempt to compare boolean with number
  • 逻辑表达式

用逻辑运算符将关系表达式或逻辑量连接起来的有意义的式子称为逻辑表达式。

逻辑运算符有3个: and or not

逻辑运算符认为false和nil是假(false),其他为真,0也是true。

and和or的运算结果不一定是true和false,而是和它的两个操作数相关。

--[[
    a and b                             -- 如果a为false,则返回a,否则返回b
    a or b                              -- 如果a为true,则返回a,否则返回b
]]--

print(4 and 5)                      --> 5
print(nil and 13)                   --> nil
print(false and 13)                     --> false
print(4 or 5)                       --> 4
print(false or 5)                       --> 5
print(true and false)               --> false
print(true or false)                    --> true
  • 字符串连接

字符串运算符是 .. 。

字符串连接,如果操作数为数字,Lua将数字转成字符串。

print (“hello” .. “everyone”)           -->hello everyone
print ( 2 .. “apples”)              --> 2  apples
s = 2 .. 3
print(s , type(s))                  --> 23    string
  • 表的构造

表(table)构造器是用于创建和初始化表的表达式。其中最简单的构造器是空构造器{},用于创建空表。

b = {x = 0, y = 1,"Monday", 109}
print(b[1],b[2],b.x,b.y)            -->Monday   109 0   1

函数

函数有两种用途:

1.完成指定的任务,这种情况下函数作为调用语句使用。例如:

print(8*9,“star” )                  --> 72  star
print(os.date())        -->07/30/14 15:17:36调用函数的时候,如果参数列表为空,必须使用()表明是函数调用

2.计算并返回值,这种情况下函数作为赋值语句的表达式使用。例如:

l = string.len(“1234567”)
print(l)                                --> 7
  • Lua函数实参和形参的匹配与赋值语句类似,多余部分被忽略,缺少部分用nil补足
function f(a, b)
    return a and b
end
c = f(3)d = f(3,4)e= f(3,4,5)
print(c, d, e)                      --> nil  4  4
  • Lua函数支持返回多个结果值
function foo0 () end                -- returns no results
function foo1 () return 'a' end         -- returns 1 result
function foo2 () return 'a','b' end -- returns 2 results
  1. 当调用作为表达式最后一个参数或者仅有一个参数时,根据变量个数函数尽可能多地返回多个值,不足补nil,超出舍去。
x,y = foo2()                        -- x='a', y='b'
x = foo2()                          -- x='a', 'b' is discarded
x,y,z = 10,foo2()                   -- x=10, y='a', z='b'
x,y = foo0()                        -- x=nil, y=nil
x,y = foo1()                        -- x='a', y=nil
x,y,z = foo2()                      -- x='a', y='b', z=nil

2.其他情况下,函数调用仅返回第一个值(如果没有返回值为nil)

x,y = foo2(), 20                    --  x='a', y=20
x,y = foo0(), 20, 30                --  x='nil', y=20, 30 is discarded
print(foo2(), 1)                    --> a 1
print(foo2() .. "x")                    --> ax
a = {foo0(), foo2(), 4}             -- a[1] = nil, a[2] = 'a', a[3] = 4
  • 函数的可变参数

Lua函数可以接受可变数目的参数,在函数形参中用三点(...)表示函数有可变的参数。Lua将函数的可变参数放在一个叫arg的表中,除了参数以外,arg表中还有一个域n表示参数的个数。

在函数参数中,固定参数和可变参数可以一起声明,但是固定参数一定要在变长参数之前声明。

function test(arg1,arg2,...)
    --...
end

基本语法

  • 赋值语句

Lua中的赋值语句和其它编程语言基本相同,唯一的差别是Lua支持“多重赋值”。

local x,y = “test”, 12              -- “test” 赋值给x,12赋值给y
  • 局部变量和块

可以用local来定义局部变量,例如: local a = “china”。local 是保留字,表示该变量是局部变量。和全局变量不同的是,局部变量的作用范围仅限于其所在的程序块。Lua中的程序可以为控制结构的执行体、函数执行体或者是一个程序块。

local x =12

if x >10 then
    local x = 0
    print(“x=”,x)                   -- 打印结果是: x=    0 ,而不是12
end
  • 控制语句

1.if语句

if 语句有3种结构:

if condition then
    statements
end

if condition then
    statements
else
    statements
end

if condition1 then
    statements
elseif condition2 then
    statements
…                                   -- 很多个elseif
    statements
end

2.while语句

while 语句语法如下:

while condition do
    statements
end

3、for循环

Lua 编程语言中 for 循环语句可以重复执行指定语句,重复次数可在 for 语句中控制。

Lua 编程语言中 for语句有两大类::

  • 数值型for循环
  • 泛型for循环

数值for循环

lua for var=exp1,exp2,exp3 do <执行体> end

var从exp1变化到exp2,每次变化以exp3为步长递增var,并执行一次"执行体"。exp3是可选的,如果不指定,默认为1。

泛型for循环

泛型for循环通过一个迭代器函数来遍历所有值,类似java中的foreach语句。

Lua 编程语言中泛型for循环语法格式:

lua --打印数组a的所有值 for i,v in ipairs(a) do print(v) end

i是数组索引值,v是对应索引的数组元素值。ipairs是Lua提供的一个迭代器函数,用来迭代数组。

4、break 和continue

break 跳出内层循环,continue不会跳出循环,但会结束本次判断。