基础特性
lua中不需要分号作为语句的结束点
注释语句
-- 单行注释
--[[
注释语句
]]--
..
操作符可以用于拼接类型,拼接后的结果是string
(nil
不支持拼接)
a = 123 .. 456
-- data type is string
-- data is 123456
print("data type is " .. type(a) .. "\n" .. "data is " .. a)
#
代表获取长度,例如可以获取字符串或者数组等的长度。获取的结果是number
类型
name = "Jelly"
-- 5
print(#name)
使用#
获取长度的规则是:末尾的nil不列入长度计算
a = {1, 2, nil, 3, 4, 5, nil, nil, nil}
-- 6
print(#a)
常用函数
输出语句
print("Hello World")
获取变量类型,将返回变量类型名的string
type()
类型系统
lua中并不需要声明变量类型,它是弱类型的语言
对于空数据而言,它们的类型是nil
a = nil
-- nil
print(type(a))
对于数值而言,它们的类型是number
a = 20.21
-- number
print(type(a))
对于字符串而言,它们的类型是string
,不管是单引号或者是双引号
a = 'Hello'
-- string
print(type(a))
对于真假而言,它们的类型是boolean
a = true
-- boolean
print(type(a))
lua中使用没有声明过的变量,不会报错,默认是nil
-- nil
print(magicData)
字符串常见操作
字符串拼接
- %d:代表与
number
拼接 - %a:代表与任意字符拼接
- %s:代表与
string
拼接
-- I am No.1
print(string.format("I am No.%d", 1))
其他类型转化为字符串
a = true
b = tostring(a)
其他常用方法
大小写转换,以及倒序字符串
-- HELLO WORLD
print(string.upper("hello world"))
-- hello world
print(string.lower("HELLO WORLD"))
-- OLLEH
print(string.reverse("HELLO"))
查找截取以及修改。lua中字符串从1开始计数,而不是0
-- 查找字符串 a的值为2
a = string.find("Hello", "ell")
-- llo
print(string.sub("Hello", 3, 5))
a = string.gsub("Hello World", "o", "O")
-- HellO WOrld
print(a)
ASCII码互转
-- 将"L"转化为ASCII码
a = string.byte("L")
-- a的值为76 a的类型是number
print(type(a))
-- 将a从ASCII转换为字符串 结果是"L"
print(string.char(a))
运算符
-
lua中没有自增自减运算符,即
--
,++
-
lua中没有符合运算符,即
-=
,+=
-
string
类型可以进行运算符操作,会自动转成number
,运算的结果也是number
a = "3.14" + 2
-
由于lua中的数都是number类型,没有整形和浮点型之分,因此
-- 0.5 print(1 / 2)
-
lua中有幂运算符号
-- 8.0 print(2 ^ 3)
-
lua中的不等于运算符是
~=
-- true print(1 ~= 20)
-
与,或和非的操作符是
and
和or
和not
。短路操作lua中仍然存在 -
lua中不支持位运算符,不支持三目运算符
if语句
a = 20
if a > 10 and a < 30 then
print("a > 10 and a < 30")
end
a = 100
if a == 20 then
print("a == 20")
elseif a == 30 then
print("a == 30")
else
print("a ~= 20")
print("a ~= 30")
end
switch语句
lua中没有switch
语句
循环语句
while循环
输出01234
num = 0
while num < 5 do
print(num)
num = num + 1
end
do-while循环
输出012345
num = 0
repeat
print(num)
num = num + 1
until num > 5
for循环
lua中的for循环语句会默认进行+1
操作,且循环终止的条件是<=
-- 输出 0 1 2 3 4 5
for i = 0, 5 do
print(i)
end
以上代码相当于
for (int i = 0; i <= 5; i++)
std::cout << i << std::endl;
如果不想采用默认的+1
操作,可以显式指明
-- 输出 0 2 4
for i = 0, 5, 2 do
print(i)
end
以上代码相当于
for (int i = 0; i <= 5; i += 2)
std::cout << i << std::endl;
如果想采用递减操作,也是显式指明的操作
-- 输出 5 4 3 2 1 0
for i = 5, 0, -1 do
print(i)
end
函数
无参数无返回值
以下代码展示函数的声明和调用,与C++相同,声明和调用的顺序是固定的
function func1()
print("this is func1")
end
func1()
除此之外还可以有类似“匿名函数”的写法
func2 = function()
print("this is func2")
end
func2()
带参数函数
同理,lua是弱类型的语言,因此函数参数不需要声明类型
function func1(a)
print(a)
end
func1(20)
更重要的,如果参数数量不匹配,那么会自动补全或丢弃
function func1(a, b)
print(b)
end
-- 补全两个nil 输出nil
func1()
-- 丢弃末尾两个参数 输出30
func1(20, 30, 430, 5)
函数返回值
由于是弱类型语言,因此不需要指明返回值类型
function cal(a, b)
return a * b
end
print(cal(2, 3))
多返回值的处理情况
function cal(a, b)
return a + b, a - b, a * b
end
data1, data2, data3 = cal(2, 3)
print(string.format("%d %d %d", data1, data2, data3))
多返回值的情况可以参照C++17中的结构化绑定。同样的多余的返回参数如果没有变量接住,那么也会被丢弃;如果声明了多个变量但返回的元素个数不够,那么会默认置空
template<typename T>
std::tuple<T, T, T> cal(T a, T b) {
return {a + b, a - b, a * b};
}
int main() {
auto [data1, data2, data3] = cal(2, 3);
std::cout << data1 << " " << data2 << " " << data3 << std::endl;
}
函数的隐藏
由于Lua中不存在函数重载,因此函数将会出现重定义的情况(即隐藏先声明的函数)
function func(a)
print(a)
end
function func()
print("empty func")
end
-- 参数100被丢弃 然后输出empty func
func(100)
变长参数
function func(...)
table = {...}
for i = 1, #table, 1 do
print(table[i])
end
end
func(100, 200, "Hello", true, 3.14)
换做C++的写法那就是
template<typename... Ts>
void func(Ts... args) {
((std::cout << args << std::endl), ...);
}
int main() {
func(100, 200, "Hello", true, 3.14);
}
函数嵌套
形成一个闭包,变量x的生命周期延长
function func(x)
return function(y)
return x + y
end
end
funcObj = func(5)
-- 输出15
print(funcObj(10))
由于C++中需要手动管理对象的生命周期,按引用捕获并不会延长变量的生命周期,所以只能使用按值捕获,因此C++的写法是
auto func(int x) {
return [=](int y) { return x + y; };
}
int main() {
// 存在捕获 所以使用auto
auto funcObj = func(5);
std::cout << funcObj(10) << std::endl;
}
表
table
是一个数据类型,不论是数组,字典或者是类等等,它们的类型都是table
数组
如下图即声明了一个数组,lua中的数组并不要求数组内元素类型的一致
a = {1, false, 3, "123"}
lua中下表索引是从1开始的,通过[]
对数组中元素进行访问。lua中数组越界并不会导致程序崩溃,它会返回nil
-- false
print(a[2])
-- nil
print(a[100])
二维数组
a = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }
for i = 1, #a do
for j = 1, #a[i] do
print(a[i][j])
end
end
自定义索引
lua中可以自定义数组的索引,如下图代码,令索引1的值为1,索引2的值为2,索引3的值为3,索引4的值为4
a = {[1] = 1, [2] = 2, [3] = 3, [4] = 4}
lua中可以跳跃的指定索引,被忽略的索引在访问时值为nil
a = {[1] = 1, [2] = 2, [3] = 3, [6] = 4}
-- nil
print(a[5])
因此在此基础上就可以实现所谓“哈希表”
a = {["name"] = "Jelly", ["age"] = 20, ["sex"] = 0}
-- age 20
-- name Jelly
-- sex 0
for k, v in pairs(a) do
print(k, v)
end
-- 直接新增元素
a["score"] = 100
-- 访问新增加的元素
print(a["score"])
ipairs和pairs迭代器遍历
a = {[0] = 0, 1, 2, [-1] = -1, [5] = 5}
-- 使用ipairs迭代器只能访问到数组中的元素1和元素2
-- ipairs遍历将会从1开始往后遍历 且只能访问连续索引的数据 遇到断序后无法继续往后访问
for k, v in ipairs(a) do
print("key:" .. k .. " value:" .. v)
end
print()
-- 使用pairs迭代器能够访问数组中的所有元素
for k, v in pairs(a) do
print("key:" .. k .. " value:" .. v)
end
至此我们可以将其理解为是C++中的std::unordered_map
,然后通过std::pair
去对键值对进行访问