笔记 - Lua 程序设计(第 2 版) Ch01~03 开始、类型与值、表达式

01 开始

print("Hello World")	--Hello World

Lua 中,换行不起任何作用。如果愿意,可以用分号分隔语句。

标识符和 C 一样,可以包含字母数字下划线,不能数字开头。尽量避免下划线跟着一串大写字母,Lua将其保留用作特殊用途。

P4 Lua 保留字

--这是行注释

--[[
这是块注释
--]]

--若想要重新启用块注释的代码
---[[  --在块注释的第一行加一个连字符即可
print(10)
--]]

全局变量

不需要声明,如果未初始化,结果是 nil

print(b)	--nil
b = 10
print(b)	--10
b = nil		--如果要删除全局变量,将其赋值为nil
print(b)	--nil

解释器

在运行脚本前,会用所有的命令行参数创建一个名为 arg 的 table,脚本名称在索引 0 上,第一个参数位于索引 1,脚本之前的选项参数位于负数索引上

02 类型与值

有八种基础类型:nil,boolean,number,string,userdata,function,thread,table

--type函数返回类型名称(返回值是string类型)
print(type("Hello"))	--> string
print(type(type(42)))	--> string

a = print	--可以像操作别的值那样操作函数值
a(type(a))	--function

nil

是一种类型,只有一个值 nil,用于区别其他任何值。用于表示无效值的情况。

boolean

false 和 nil 视为假,其他所有值都是真,所以数字零和空字符串也是真

number

用于表示实数。lua 没有整数类型。

--可以使用科学计数法
print(5e+10)	-->50000000000

string

Lua 的字符串是不可变的值,并且是自动内存管理机制所管理的对象,无需担心字符串的分配和释放。

--字面字符串用单双引号皆可
a = "a line"
b = 'another line'

--可以包含类似C的转义序列
c = "hi\nhello"

--可以用转义序列,通过数值指定字符
d = "hi\065hello"
print(d)	-->hiAhello

--用双方括号界定字符串,不会解释转义序列
--回忽略第一个换行符
e = [[
first
second
]]

--如果字符串中出现]]
--可以在前后的双方括号之间加上数量相等的等号
--对块注释同样适用
f = [===[
first
a[b[]]
]===]

数字和字符串存在自动转换

print("10" + 1)		-->11
print("10" * "2")	-->20

-- ..是字符串连接符
print(10 .. 20)		-->1020

--用函数显式转换
print(tonumber("100") * 30)			-->3000
print(tostring(12.45) .. "hello")	-->12.45hello

-- #是长度操作符
print(#(tostring(12.45) .. "hello")) -->10

table

实现了关联数组

a = {}				--创建table
a[5] = 6
a["index"] = 100
print(a[5])
print(a["index"])
print(a.index)		--语法糖,注意只有字符串索引可以这么用

--table是一种动态分配的对象,程序仅持有一个对它们的引用(指针)
b = a
b[5] = 1000
print(a[5])   -->1000

b = nil --只有a还在引用table
a = nil --没有对table的引用了
--此时Lua的垃圾收集器自动删除table,回收内存

如果要表示传统的数组,用整数 key 即可:

a = {}
for i = 1, 10 do
  a[i] = i
end
for i = 1, 10 do
  print(a[i])
end
--在Lua的习惯中,数组通常以1作为索引起始值

长度操作符的习惯用法:

print(a[#a])	--打印最后一个值
a[#a] = nil		--删除最后一个值
a[#a+1] = 100	--把100加到列表末尾

对于包含空隙的数组,长度操作符会出问题

a = {}
a[1000] = 6;
print(#a)	-->0

--可以使用table.maxn,返回table的最大正索引数
print(table.maxn(a))  -->1000

function

函数可以存储在变量中,可以通过参数传递给其他函数,可以作为函数的返回值。程序可以重新定义函数,或者删除某些函数。

userdata 和 thread

userdata 将任意 C 语言数据存储到 lua 变量中,只能进行赋值和相等性测试。

thread 详见第 9 章

03 表达式

算数操作符

二元:+ 加 - 减 * 乘 / 除 ^ 指数 % 取模

一元:- 负号

其中,取模的定义如下:

a % b == a - floor(a/b)*b

对于整数,计算结果的符号与第二个参数相同

对于实数,x%1 得到小数部分,x-x%0.01 是 x 精确到小数点后两位的结果

关系操作符

< > <= >= == ~=

全部返回 true 或者 false

注意 == 和 ~= 可以用于任意两个值。如果类型不同则不相等。nil 只和自身相等

对于 table,userdata,Lua 作引用比较

对于字符串和数字的大小比较会引发一个错误。

逻辑操作符

and or not

false 和 nil 视为假,其他都是真

对 and,如果第一个操作数为假,返回第一个操作数,否则返回第二个

对 or,如果第一个操作数为真,返回第一个操作数,否则返回第二个

and 和 or 都使用短路求值,类似 cpp

x = x or v
--等价于
if not x then x = v end

max = (x > y) and x or y
--等价于c中的
--max = x > y ? x : y
--前提是x不为假

not 永远只返回 true 或者false

字符串连接

… 操作符。因为 Lua 中字符串是不可变的,因此连接操作符只会创建一个新的字符串

优先级

P22

指数操作符和连接操作符是右结合的,其他都是左结合的。

table 构造式

--a[1] = "A",以此类推
a = {"A", "B", "C"}
for i = 1, #a do
  print(a[i])
end

特殊的语法:

a = {x = 10, y = 20}
print(a.x == 10)	-->true

每当 Lua 处理构造式,会先创建新的 table 然后初始化它。用 Lua 新建链表的代码:

list = nil
for line in io.lines() do
  list = {next = list, value = line}
end
-- 输出
local l = list
while l do
  print(l.value)
  l = l.next
end

注意,真实的 Lua 程序很少使用链表。

更通用的格式如下:

opnames = {["+"] = "add", ["-"] = minus}
--可以嵌套
polyline = {color = "blue", {x = 5, y = 10}}
--等价于
polyline = {["color"] = "blue", {["x"] = 5, ["y"] = 10}}

在构造是中可以用分号代替逗号,功能没有不同,可以加强可读性

上一篇:Lua_模块与包_加载机制_C包_脚本卸载_大G表(13)


下一篇:Lua_数据_一维数组_多维数组_数组索引(10)