文章目录
-
- 数据类型
- 流程控制
- 数学计算
数据类型
Lua中的数据类型只有8种:
| boolean | 布尔 | number | 双精度浮点数 |
| string | 字符串 | nil | 未赋值(不存在的)变量 |
| function | 函数 | table | 键值对数据结构 |
| thread | 线程 | userdata | C数据结构 |
大部分大家都不陌生,只有userdata比较吊诡。
C:\\Users\\Laser>lua
Lua 5.1.4 Copyright (C) 1994–2008 Lua.org, PUC–Rio
> print(type(a)) –a虽然没有创建,但默认为全局变量
nil –未创建的变量,默认未nil
> a = 3
> print(a)
3
> print(type(a))
number –没有整型,全都是浮点型
> a = {} –创建一个空表
> print(a)
table: 00AFA0B8
> a = {"A","B","C"} –默认key为自然数列的表
–下面的for循环打印表的键和值
> for key,val in pairs(a) do
>> print("key:",key,"value:",val)
>> end
key: 1 value: A
key: 2 value: B
key: 3 value: C
> print(a[1]) –表中的值可以用[]来引用
A
> a["a"] = "A" –也可以用[]来增加键值对,或对已有键重新赋值
> print(a["a"])
A
> a = {["a"]="A",["b"]="B"} –通过键值对的方式创建表
> for key,val in pairs(a) do
>> print("key:",key,"value:",val)
>> end
key: a value: A
key: b value: B
Lua是函数式语言,函数作为一种数据类型,也像其他数据类型一样可以作为变量。
–经典的阶乘函数
> function fac(n)
>> if n==0 then
>> return 1
>> else
>> return n*fac(n–1)
>> end
>> end
> print(fac(5))
120
–这个函数的输入为一个函数func和一个值
> function printFunc(func,value)
>> for i = 0,value do
>> print(func(i)) –打印不大于value所有值的阶乘
>> end
> printFunc(fac,5)
1
1
2
6
24
120
>
thread是Lua中的一种数据类型,顾名思义就是线程,或者更准确地说叫做协同式多线程(collaborative multithreading),简称协程(coroutines)。不同于操作系统中的线程,在Lua中,协程并不能实现“并行”工作,而是非常密切地“协同”工作。
Lua将所有关于协同程序的函数放在一个名为coroutine的table中,函数create可以将一个函数转化为一个协程。
> function fun1()
>> print("I'm fun1")
>> end
> co1 = coroutine.create(fun1)
> print(co1)
thread: 006BBF08 –co1是一个协程
协程的创建与回收过程可分为四种状态,即挂起(suspand)、运行(running)、死亡(dead)以及正常(normal)。一个协程被创建之后,并不会马上执行,而是会处于挂起状态。
> print(coroutine.status(co1))
suspended –协程创建之后是
> coroutine.resume(co1)
–I'm fun1 –协程被执行
> print(coroutine.status(co1))
dead –执行之后,状态变为dead
> print(type(co1))
thread –但这个变量还在,并没有被销毁
如果仅仅如此,那并没有体现出“协作”的特性,不过有了yield的加入,事情就变得有趣起来了。对于熟悉Python的朋友,可能也会猜到yield的作用
>function fun2()
>> for i = 1,10 do
>> print("co2:",i)
>> coroutine.yield()
>> end
>> end
> co2 = coroutine.create(fun2)
> coroutine.resume(co2)
co2: 1 –当遇到yield之后,协程被挂起
> coroutine.resume(co2)
co2: 2
> coroutine.resume(co2)
co2: 3
> print(coroutine.status(co2))
suspended
— 通过匿名函数新建一个协程co3
> co3 = coroutine.create(function()
>> for i = 1,5 do
>> print("co3:",i)
>> coroutine.resume(co2)
>> print("status of co3:",coroutine.status(co3))
>> print("status of co2:",coroutine.status(co2))
>> end
>> end
>> )
> coroutine.resume(co3)
co3: 1
co2: 4
status of co3: running –co3处于执行状态
status of co2: suspended –co2遇到yield被挂起
–…3次…–
co3: 5
co2: 8
status of co3: running
status of co2: suspended
尽管我们对线程都不陌生,但将thread作为一种数据类型还是很离奇的,但Lua中更离奇的数据类型还要数userdata。但其功能却是直接而必要的,userdata的作用在于为Lua和其他语言提供了一种良好的交互。
流程控制
三种常见的循环格式如下。
| while(i<b) do…i = i+1end | for i=0,b,1 do…end | repeat…until(i=b) |
其条件语句为
if(bool) then
…
else
…
end
符合大多数程序员的编程直觉。
Lua不出意外地支持break,与其他语言几乎相同。但令人不解的是,Lua中提供了为人所诟病的goto语句,可能是面向底层的原因。
不过goto语句似乎无法在命令行中运行,需要编辑脚本才可以。
–goto.lua
a = 1
::label:: print(a)
a = a+1
if a<4 then
goto label
end
然后在命令行中执行
lua goto.lua
1
2
3
但是,如果将goto封装到函数中,则可以在交互式命令行中调用。Lua中,函数通过function进行调用。
> function test()
>> a = 1
>> ::label:: a = a+1
>> print(a)
>> if a<5 then
>> goto label
>> end
>> end
> test()
2
3
4
5
>
数学计算
在Lua中,通过require进行模块的引用,其中,math中封装了一些常用的数学函数,除了三角函数sin, cos, tan, asin, acos, atan; 以及exp, log, log10, abs, max, min, pow, mod, sqrt这些顾名思义的常用函数之外,还包括:
> math.ceil(1.1) –向上取整
2
> math.floor(1.9) –向下取整
1
> math.modf(1.2) –将整数和小数分开
1 0.2
> math.rad(30) –角度转弧度
0.5235987755983
> math.deg(math.pi/2) –弧度转角度
90.0
> math.random(10,20) –10-20之间的随机数
16
矩阵是科学计算中不可回避的数学对象,在Lua中可以通过多维table来表示
> mat = {}
> N = 20
> for i = 1, N do
>> mt = {}
>> for j = 1, N do
>> mt[j] = i+j
>> end
>> end
> mat
基于这种表示方法,可以构建一整套矩阵运算规则。然而如果想直接进行矩阵运算,最好还是下载一些成熟的矩阵计算包,例如scilua。下载之后进入ulua/bin/目录,依次运行
upkg add sci
upkg add sci-lang
scilua的子模块alg中封装了矢量以及矩阵
> alg = require("sci.alg")
> x = alg.mat(3,3) –创建一个3×3的全0矩阵
> for i = 1,#x do –矩阵也可以作为向量
>> x[i] = i
>> end
> print(x)
+1.000000,+2.000000,+3.000000
+4.000000,+5.000000,+6.000000
+7.000000,+8.000000,+9.000000
> y = x:new() –创建与x行列相同的全0矩阵
> alg.mul(y,x,x) –y=x*x
> print(y)
+30.00000,+36.00000,+42.00000
+66.00000,+81.00000,+96.00000
+102.0000,+126.0000,+150.0000



