a = a * 2
b = a * b
a = a * 2;
b = a * b
a = a * b; b = a * b
a = a * b b = a * b
在交互模式中输入的一行内容会被解释器当作一个完整的程序块,如果这一行的内容不足以构成一个完整的程序块,就会等待输入
Ctrl + Z
是 end-of-file 控制字符,在 dos 中是这个快捷键os.exit()
标准库中的退出函数dofile("文件路径 / 需要转义")
加载函数库-- 阶乘函数
function fact(n)
if n == 0 then
return 1 --0 的阶乘是 1
else
return n * fact(n - 1) -- 3 的阶乘, 3 * 2 * 1
end
end
print("Enter a number:")
a = io.read("*number") -- 读取用户输入且需为数字类型的
print(fact(a)) --调用阶乘函数,并传入实参 a
-- lib1 函数库
function norm(x, y)
return (x ^ 2 + y ^ 2) ^ 0.5 -- 两个数的平方和再开平方根
end
function twice(x)
return 2 * x -- 一个数的两倍
end
_PROMPT = ">lua" -- 修改交互模式中的提示符,默认为 >
if
then
elseif
end
for
do
in
while
repeat
until
if 条件表达式 then
elseif 条件表达式 then
end
for 控制变量, 终止变量, 步长 do
<循环体>
end
a = {}
for i,v in ipairs(a) do
<循环体>
end
while i < 10 do
i = i + 1
print(i)
end
repeat
i = 0
i = i + 1
until i > 10
true
false
and
or
not
function
local
nil
nil == nil
是相等的and
和 And
不同,lua 区分大小写true
和 false
false
和 nil
都可以用作表示「真」""
和数字 0
--
--[[]]
---[[ <代码块> --]]
--[==[ <多行注释> ]==]
nil
nil
即可-i
先执行程序块,后进入交互模式-e
直接执行代码块-l
加载库文件LUA_INIT
的环境变量@文件名
的话,就执行这个文件lua -i -e "hello" script a b
arg[0] = "script"
arg[1] = "a"
arg[-1] = "hello"
arg[-2] = "-e"
arg[-3] = "-i"
...
三个点,作为函数参数传递时表示传递所有参数type()
可以返回一个值的类型名称type()
的返回结果永远是 string
类型的print(type(3)) -- number
print(type("a")) -- string
print(type({"a", "b", "c"})) -- table
print(type(io.read)) -- function
print(type(true)) -- boolean
2e2
表示 200long
tonumber()
用于将一个字符串显式的转换为数字类型在 lua 中,有两个布尔值一个是 true
表示为「真」,一个是 false
表示为「假」
但,这两个值不是用来表示条件的唯一值,在 lua 中 除 nil
和 false
外的任何值,都可以用来表示
「真」, 包括空字符串 ""
和数字 0
nil
..
字符串连接符,用于连接两个字符串,但数字类型使用时需要用空格隔开#
长度操作符,后跟字符串,可以获取字符串长度[[]]
在期内的特殊字符不需要转义[==[ <多行注释> ]==]
可以正确打印多行注释的内容"3" + 4
这样的值会是 number
类型,发生了运行时隐式转换print("\97" == "a") -- 在 ASCII 编码表中,\97 表示为 a
print(type(3 .. "")) -- string
print(3..4) --报错
print(3 .. 4) -- 34
print(#"hello") -- 5
-- 获取子串,证明字符串是不可变的值
a = "hello"
b = a .. " ,world"
print(a) -- hello
print(b) -- hello, world
a = [[
芜湖
]]
a = [==[
--[[
print("多行注释")
print("多行注释")
]]
]==]
print(type("3" + 4)) -- number
tostring()
.. ""
任意数字连接一个空字符串即可转换为字符串是对象,由自动内存回收器进行分配和释放
table 没有固定大小,可以动态添加元素
{}
是 table 构造式,用来创建一个 table
#
长度操作符可以获取 table 的大小
table 中的元素在未被初始化前都是 nil
可以将 table 中的元素赋值 nil
来进行删除
如果 table 中间部分的元素值为 nil
就说明这是一个有「空隙」的 table
有「空隙」的 table 要使用 table.maxn()
来返回这个函数的最大正索引数
table 可以用来表示模块、包、对象
table 中的索引可以是任何值,除了 nil
table 是匿名的
程序仅保留了对 table 的一个引用
一个仅有 table 的变量和 table 自身并没有关系
a.x
等价于 a["x"]
是以字符串为索引的
a[x]
是以变量 x
为索引的
a = {}
for i = 1, 10 do
a[i] = i
print(a[i])
end
for i = 1, #a do
print(a[i])
end
print(a[10]) -- 10
print(#a) -- 10
a[10] = nil
print(#a) -- 9
a[10000] = 666
print(#a) -- 9
print(table.maxn(a)) -- 10000
a = {}
b = {}
c = a
print(type(a == b)) -- false
print(type(a == c)) -- true
x = "y"
a["x"] = 666
a["y"] = 777
print(a.x) --666
print(a[x]) -- 777
表达式用于表示值
在 lua 中,函数调用,函数定义,数字常量、字面字符串,变量,一元和二元操作符,table 构造式都是表达式
-
负号+
-
减号*
/
%
^
-- % 的技巧
-- x % 1
print(3.13 % 1) -- 得到小数部分
-- x - x % 1
print(3.14 - 3.14 % 1) -- 得到整数部分
-- x - x % 0.1
print(3.14 - 3.14 % 0.1) -- 得到整数部分 + 一位小数部分
-- x - x % 0.01 以此类推,是整数部分 + 两位小数部分
>
<
>=
<=
==
相等性判断~=
不等性判断and
第一个操作数为假,返回第一个,否则返回第二个or
第一个操作数为真,返回第一个,否则返回第二个not
只会返回 true
或 false
-- 短路操作的使用技巧
print(x = x or v) -- 初始化一个值,如果 x 为 nil 没有被初始化过,就赋值 v
-- 等价于
if not x then
x = v
end
-- 实现 C 语言中的三元操作符, a ? b : c
print((a and b) or c) -- b 必须为真,才可以这样操作
-- 等价于
if a == true then
return b
elseif a == false then
return c
end
-- 实现返回两个数中的较大值
max = (x > y) and x or y -- 因为 lua 将数字视为「真」
-- 等价于
if x > y then
return x
else
return y
end
..
字符串连接^
-
负号not
#
*
/
%
+
-
减号..
字符串连接>
<
>=
<=
==
~=
and
or
a = {x = 10, y = 20} -- 等价于 a.x = 10, a.y = 20
a = {
color = {"red", "green", "blue"}
width = 200,
height = 300
}
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
options = {["+"] = "add", ["-"] = "sub",
["*"] = "mul", ["/"] = "div"}
print(options["+"]) -- "add"
a, b = 1, 2
nil
a, b = 1, 2
x, y = y, x -- 交换变量
a, b = 1 -- a = 1, b = nil
a, b = 1, 2, 3 -- a = 1, b = 2, 3 被抛弃
a, b = f() -- a 接收函数 f 的第一个返回值,b 接收第二个
a, b, c = 0, 0, 0 -- 初始化赋值
do <要执行的内容> end
将要执行的内容包裹在一个块内local
用来声明一个局部变量a = 3
b = 0
if a then
local a = 5
b = a -- 将 then 块内的局部变量 a ,保存到全局变量 b 中
print(a)
end
print(a) -- 3
print(b) -- 5
do
-- code block
end
if
elseif
else
if 条件表达式 then
<执行体> -- 符合条件表达式执行
end
if 条件表达式1 then
<执行体 1> -- 符合条件表达式 1 执行
elseif 条件表达式2 then
<执行体 2> -- 符合条件表达式 2 执行
end
if 条件表达式 then
<执行体 1> -- 条件表达式为真时执行
else
<执行体 2> -- 条件表达式为假是执行
end
for
while
条件表达式为假时退出repeat ... until
条件表达式为真时推出,条件测试是在循环体之后做的,因此循环体至少会执行一次break
或 return
在循环正常结束前提前结束它for exp1, exp2, exp3 do
<循环体>
end
while 条件表达式 do
<循环体>
end
repeat
<循环体>
until 条件表达式
a = 20
repeat
local a = 0
print(a)
until a == 0 -- 可访问在 repeat 块内声明的 a, 而不是全局变量 a
for i = 10, 0, -1 do
print(i)
end
ipairs()
用来遍历数组i
每次循环时都会赋予一个新的索引值,v
则是索引值所对应的元素a = {1, 2, 3, 4, 5, 6}
for i,v in ipairs(a) do
print(i)
print(v)
end
for i,v in pairs(a) do
print(i)
print(v)
end
days = {"第一天", "第二天", "第三天"}
revdays = {}
for i, v in ipairs(days) do
revdays[v] = i -- 逆向数组,将数组索引和数组元素调换,可获取数组元素的位置
end
print(revdays["第二天"]) -- 获取第二天所在位置
break
用于结束一个循环,跳出内层循环后在外层循环中继续执行return
用于返回函数结果或简单的结束函数的执行return
return
return
或 break
后的语句将无法执行到do ... end
块包裹 return
,用与调试,即调用函数但不执行函数内容的情况a = 1
if a then
print("hello")
break
print("world") -- 会报错
end
for i = 1, 10 do
print(i)
if i > 3 then
break -- 只会打印 1 2 3 4 然后就跳出循环了
end
end
-- 调试
function foo(...)
do
return
end
print("执行 foo 函数") -- 不会打印
end
foo(1, 2 ,3)
print("hello") -- 用来完成打印任务,视为一条语句
a = os.date() -- os.date() 用来返回日期,视为一句表达式
()
()
可以省略()
print "hello" -- hello
print {1, 2, 3} -- 1 2 3
print(os.date) -- 当前日期
function
是创建函数的关键字function add
add 是函数的名称function add(n)
n 是函数的形式参数,简称为形参add(4)
4 是调用 add()
函数时的实际参 ,简称为实参nil
function foo(a, b)
return a or b
end
foo(1) -- a = 1, b = nil
foo(1, 2) -- a = 1, b = 2
foo(1, 2, 31) -- a = 1, b = 2, 多余的 31 被抛弃
-- 面向对象式调用
o.foo(o, x)
o:foo(x) -- 与上面的效果一样,: 冒号操作符,隐式的将 o 作为第一个参数
string.find("you are cool", "are") -- 5 7 返回找到的字符串的开头位置和结尾位置
-- 查找数组中的最大元素,并返回这个元素的所在位置
function maximum(a)
local val = 1
local max = a[val]
for i,v in ipairs(a) do
if max < a[i] then
max = a[i]
val = i
end
end
return max, val
end
a = {1, 2, 55, 22, 29, 4}
maximum(a)
nil
来补充缺失的值function foo() end
function foo1() return "a" end
function foo2() return "a", "b" end
-- 第一种情况,最后(或仅有)的一个表达式
x, y = foo1() -- x = a, y = b
-- 第二种情况,没有返回值
x = foo() -- nil
-- 第二种情况,没有返回足够多的返回值
x, y, z = foo1() -- x = a, y = b, z = nil
-- 第三种情况,不是表达式中的最后一个元素
x, y = foo2(), 10 -- x = a, y = 10
function foo() end
function foo1() return "a" end
function foo2() return "a", "b" end
-- 第四种情况,作为 print 函数中的最后一个(或仅有的)实参
print(foo()) -- nil
print(foo1()) -- "a"
print(foo2()) -- "a" "b"
print(foo1() .. "test") -- "atest"
print(foo2() .. "test") -- "atest"
function foo() end
function foo1() return "a" end
function foo2() return "a", "b" end
-- 函数调用是 table 中的最后一个元素
a = {foo2()} -- a = {"a", "b"}
a = {foo2(), 10} -- a = {"a", 10}
function foo0() end
function foo1() return "a" end
function foo2() return "a", "b" end
function foo(i)
if i == 0 then return foo0()
elseif i == 1 then return foo1()
elseif i == 2 then return foo2()
end
end
print(foo(1)) -- a
print(foo(2)) -- a, b
print(foo(0)) -- 无返回值,在交互模式中会是一个空行
-- () 包裹
print((foo(1)) -- a
print((foo(2)) -- a
print((foo(0)) -- nil ,应该是强制返回了一个未初始化的值,因为 foo0() 没有返回值
print(unpack{10, 20, 30}) -- 10 20 30
a, b = unpack{10, 20, 30} -- a = 10, b = 20
-- 调用任意函数 f, 而所有的参数都在数组 a 中
-- unpack 将返回 a 中的所有值,这些值作为 f 的实参
f(unpack(a))
f = string.find
a = {"hello", "ll"}
f(unpack(a)) -- 3 4 等效于 string.find("hello", "ll")
function unpack(t, i)
i = i or 1
if t[i] then
return t[i], unpack(t, i + 1)
end
end
...
三个点表示该函数接收不同数量的实参...
三个点,此时 ...
三个点是作为一个表达式使用的...
三个点的行为类似一个具有多重返回值的函数,它返回的是当前函数的所有变长参数select
时,必须传入一个固定参数 selector
(选择开关) 和一系列变长参数selector
为数字 n ,那么 select
返回它的第 n 个可变实参select
只能为字符串 "#"
,这样 select
会返回变长参数的总数,包括 nil
-- 返回所有参数的和
function add(...)
local s = 0
for i, v in ipairs{...} do -- 表达式{...}表示一个由变长参数构成的数组
s = s + v
end
return s
end
print(add(3, 4, 5, 100)) -- 115
-- 调试技巧 ,类似与直接调用函数 foo ,但在调用 foo 前先调用 print 打印其所有的实参
function foo1(...)
print("calling foo:", ...)
return foo(...)
end
-- 获取函数的实参列表
function foo(a, b, c) end
function foo(...)
local a, b, c = ...
end
-- 格式化文本 string.format ,输出文本 io.write
-- 固定参数一定要在变长参数之前
function fwrite(fmt, ...)
return io.write(string.format(fmt, ...))
end
fwrite() -- fmt = nil
fwrite("a") -- fmt = a
fwrite("%d%d", 4, 5) -- fmt = "%d%d" , 变长参数 = 4, 5
for i = 1, select('#', ...) do
local arg = select('#', ...)
<循环体>
end
()
是可有可无的os.rename -- 文件改名,希望达到的效果 os.rename(old = "temp.lua", new = "temp1.lua")
-- lua 不支持注释的写法
rename = {old = "temp.lua", new = "temp1.lua"}
function rename (arg)
return os.rename(arg.old, arg.new)
end
x = Window{x = 0, y = 0, width = 300, height = 200, title = "Lua", background = "blue", border = "true"}
-- Window 函数根据要求检查必填参数,或为某些函数添加默认值
-- 假设 _Window 是真正用于创建新窗口的函数,要求所有参数以正确次序传入
function Window(options)
if type(options.title) ~= "string" then
error("no title")
elseif type(options.width) ~= "number" then
error("no width")
elseif type(options.height) ~= "height" then
error("no height")
end
_Window(options.title,
options.x or 0 -- 默认值
options.y or 0 -- 默认值
options.width, options.height,
options.background or "white" -- 默认值
options.border -- 默认值为 false(nil)
)
end
因为,目前只学到第五章函数篇,所以只有前五章的复习汇总,很基础,也很重要,也祝愿大家可以踏踏实实地打好地基。