img

图片来自官网

Lua由巴西里约热内卢天主教大学PUC-Rio的一个团队设计、实施和维护。“Lua”(发音为LOO-ah)在葡萄牙语中的意思是"月亮”。

Lua 是一种强大、高效、轻量级、可嵌入的脚本语言。它支持过程编程、面向对象编程、函数编程、数据驱动编程和数据描述。

Lua 将简单的过程语法和基于关联数组和可扩展语义的强大数据描述构造相结合。Lua 是动态键入的,通过使用基于寄存器的虚拟机解释字节码来运行,并且具有具有增量垃圾回收的自动内存管理,因此非常适合配置、脚本编写和快速原型设计。

安装

Lua官网下载:www.lua.org/download.html

1
2
3
4
tar zxvf lua-5.x.x.tar.gz
cd lua-5.x.x
make linux test
make install

注释

1
2
3
4
5
6
--单行注释

--[[
多行注释
多行注释
--]]

变量

数据类型

数据类型 描述
nil 表示一个无效值,只有值nil属于该类,相当于条件表达式中的false
boolean true(0,空字符串是true)或者false(只有nil和false是false)
number 双精度类型的实浮点数
string ‘‘或"“或[[]]表示
function c或lua编写的函数
userdata 用来将任意c数据结构保存到lua变量中
thread 用来实现coroutine
table 关联数组

Lua中的变量默认是全局变量,哪怕是语句块或函数里。除非用local显示声明为局部变量。

变量的默认值均为nil

1
2
a = 5
local b = "hey"

lua可以对多个变量同时赋值,赋值语句右边的值会依次赋给左边的变量。

1
2
3
4
5
6
7
8
--[[
1. 变量个数 > 值个数  按变量个数补足nil
2. 变量个数 < 值个数  多余值被忽略
]]--
a, b, c = 0, 1 -->0 1 nil
a, b = a+1, b+1, b+2  -->1,2 b+2忽略
a, b, c = 0  -->0 nil nil
x, y = y, x  -- swap x, y

流程控制

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)

for

1
2
3
4
5
6
sum = 0
for i=1, 100 do
--> for i = 1, 100, 2 do
--> 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

if-else

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
a = 100
if(a == 10) then
    print("a == 10")
elseif a == 20 then  -->可以不带括号
    print("a == 20")
elseif(a == 30) then
    print("a == 30")
else
    print("a nothing")
end

函数

递归

1
2
3
4
5
6
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
function newCounter()
    local i = 0
    return function()
        i = i + 1
        return i
    end
end

ci = newCounter()
print(c1())
print(c1())

多返回值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function maximum(a)
    local mi = 1
    local m = a[mi]
    for i,val in ipairs(a) do
        if val > m then
            mi = i
            m = val
        end
    end
    return m, mi
end
print(maximum({8,10,23,12,3,9}))

table & metatable

表table

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
atable = {}

atable[1] = "lua"
atable = nil --移除引用,lua垃圾回收会释放内存

arr = {"string", 100, "haoel", function() print("cooool") end}
for i = 1, #arr do
--for k, v in pairs(arr) do
--  print(k, v)
    print(arr[i])
end

元表metatable

Lua提供了元表(metatable),允许我们改变table的行为(例如:两表相加),每个行为关联了对应的元方法。

  • setmetatable(table,metatable):对指定table设置元表(metatable),如果元表中存在__metatable键值,setmetatable会失败。
  • getmetatable(table): 返回对象的元素。
1
2
3
4
5
6
atable = {}
ametatable = {}
setmetatable(atable, ametatable)
--另一种写法
atable = setmetatable({},{})
getmetatable(atable)
模式 描述
__add(a, b) a + b
__sub(a, b) a - b
__mul(a, b) a * b
__div(a, b) a / b
__mod(a, b) a % b
__pow(a, b) a ^ b
__unm(a) -a
__concat(a, b) a..b
__len(a) #a
__eq(a, b) a == b
__lt(a, b) a < b
__le(a, b) a <= b
__index(a, b) a.b
__newindex(a, b, c) a.b = v
__call(a,…) a(…)

__index

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
arrtable = setmetatable({key1 = "value1"},{
    __index = function(arrtable, key)
        if key == "key2" then
            return "cooooooool"
        else
            return nil
        end
    end
})

arrtable = setmetatable({key1 = "value1"},{__index = {key2 = "metablevalue"}})
print(arrtable.key1, arrtable.key2)

如上所示,Lua查找一个表元素时分为以下3步:

  1. 在表中查找,如果找到,返回该元素,找不到则继续。
  2. 判断该表是否有元表,如果没有元表,返回nil,有元表则继续。
  3. 判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1,2,3;如果__index方法是一个函数,则返回该函数的返回值。

__add

 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
function table_maxn(t)
    local mn = 0
    for k, v in pairs(t) do
        if mn < k then
            mn = k
        end
    end
    return mn
end

arrtable = setmetatable({1,2,3}, {
    __add = function(table1, table2)
        for i = 1, table_maxn(table2) do
            table.insert(table1, table_maxn(table2)+1, table2[i])
        end
        return table1
    end
})

secondtable = {4,5,6}

arrtable = arrtable + secodtable

for k, v in ipairs(arrtable) do
  print(k,v)
end

模块与包

require函数用于加载模块,执行require后返回一个由模块常量或函数组成的table,并且还会定义一个包含该table的全局变量。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
module = {}
module.constant = "this is a const"

function module.func1()
    io.write("func1()")
end

local function func2()
    print("this is a private func")
end

function module.func3()
  func2()
end

return module
1
2
3
4
5
6
7
require("module")
print(module.constant)
module.func3()

local m = require("module")
print(m.constant)
m.func3()

协程

方法 描述
coroutine.create() 创建coroutine,返回coroutine,参数是一个函数
coroutine.resume() 重启coroutine,和create配合使用,启动coroutine
coroutine.yield() 挂起coroutine,将coroutine设置为挂起状态
coroutine.status() 查看coroutine的状态(dead, suspended, running)
coroutine.wrap() 创建coroutine,返回一个函数,调用该函数,进入coroutine,与create功能重复
coroutine.running() 返回正在跑的coroutine的线程号
 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
local newProductor

function productor()
  local i = 0
  while true do
    i = i + 1
    send(i)
  end
end

function consumer()
  while true do
    local i =receive()
  end
end

function receive()
  local status, value = coroutine.resume(newProductor) --返回参数
  return value
end

function sed(x)
  coroutine.yield(x)
end

newProductor = coroutine.create(productor)
consumer()

错误处理

语法错误,运行错误。

assert

assert检查第一个参数,若正确,不做任何事,否则返回第二个参数为错误信息。

1
2
3
4
local function cool(a)
  assert(type(a) == "number", "a不是一个数字")
  return a
end

error

终止正在执行的函数,并返回message的内容作为错误信息。

1
2
3
4
error (message [, level])
-- 1. level=1 默认,返回error位置,文件+行号
-- 2. level=2 指出哪个调用error的函数的函数
-- 3. level=0 不添加错误位置信息

面向对象

 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
Shape = {area = 0}

function Shape:new(o, side)
  o = o or {} --> or运算符 A or B若A为true,则返回A,否则返回B
  setmetatable(o, self)
  self.__index = self -->防止扩展后被改写
  side = side or 0
  self.area = side * side;
  return o
end

function Shape:printArea()
  print("area is: ",self.area)
end
myshape = Shape:new(nil,10)
myshape:printArea()


Rectangle = Shape:new()
--派生类方法
function Rectangle:new(o, length, breadth)
  o = o or Shape:new(o)
  setmetatable(o, self)
  self.__index = self
  self.area = length * breadth
  return o
end

function Rectangle:printArea()
  print("Rectangle area is: ",self.area)
end

myrectangle = Rectangle:new(nil, 10, 20)
myrectangle:printArea()

参考连接