惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
The Blog of Author Tim Ferriss
博客园 - 司徒正美
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
有赞技术团队
有赞技术团队
量子位
S
SegmentFault 最新的问题
博客园 - 聂微东
博客园 - 【当耐特】
J
Java Code Geeks
美团技术团队
Hugging Face - Blog
Hugging Face - Blog
H
Help Net Security
V
V2EX
人人都是产品经理
人人都是产品经理
博客园 - Franky
罗磊的独立博客
Engineering at Meta
Engineering at Meta
A
About on SuperTechFans
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
云风的 BLOG
云风的 BLOG
Y
Y Combinator Blog
Apple Machine Learning Research
Apple Machine Learning Research

崎径 其镜

Unity 项目迁移鸿蒙(三):SDK 接入 Unity 项目迁移鸿蒙(二):打包与调试 Unity 项目迁移鸿蒙(一):环境准备与工程结构 Unity 项目迁移鸿蒙(一):环境准备与工程结构 阿里云实人认证iOS SDK 升级 阿里云实人认证iOS SDK 升级 DeepSeek V4 Flash 接入 Codex 教程 DeepSeek V4 Flash 接入 Codex 教程 Unity CVE-2025-59489 漏洞修复实践(Google Play 合规) Unity CVE-2025-59489 漏洞修复实践(Google Play 合规) 从零配置 VS Code C++ 环境 从零配置 VS Code C++ 环境 力扣笔记 力扣笔记 一文详解Hexo 博客搭建 一文详解Hexo 博客搭建 Unity 游戏的 Google Play 16 kb页面对齐处理 Unity 升级到 2022 踩坑记录(URP / 黑屏 / HTTP) Unity 升级到 2022 踩坑记录(URP / 黑屏 / HTTP) Android Google Play 16 KB 页面对齐适配指南 Android Google Play 16 KB 页面对齐适配指南 iOS 应用开启包外存储访问(文件共享) iOS 应用开启包外存储访问(文件共享) xlua学习笔记 xlua学习笔记 Lua新知 EFK日志分析系统的搭建 EFK日志分析系统的搭建 使用贝塞尔曲线实现道具随机飞动效果 使用贝塞尔曲线实现道具随机飞动效果
Lua新知
Anqi Zhao · 2021-05-10 · via 崎径 其镜

两年没有碰过Lua了,总觉得得要捡起来。现在从头到尾再过一遍,总结一些东西。之前根据菜鸟学的时候,使用了5.1.1的版本。与现在常用的版本相悖。因此这次我使用了:zerobrane studio,它可以方便切换版本,能实现很好的练习效果。

关于多行注释的安全问题

如果直接使用默认的--[[--]]来进行多行注释的时候,如果遇到table包table的情况会直接结束注释:





a = 1

可以使用另一种方法来进行多行注释,避免这个问题:





a = 1
]=]

当然,最安全的方法还是使用IDE的快捷键进行注释.IDE会在每行的前面加单行注释,避免错误的发生.

多行字符串安全问题

多行字符串,也会出现类似于上面的情况:

str = 
[[
话说
这个东西
好像打印不出来
就是这个
table[table[idx]]
咋办啊
]]
print(str)

运算符相关

#运算符取的是最大索引的值,如果删除了中间的值,获得的结果不会改变:

tb_a = {1, 2, 3}
print (#tb_a)

tb_a[2] = nil
print (#tb_a)

但是这种情况仅限于Lua 5.1 ,Lua5.3和Lua5.4结果是1。

模拟三目运算符的and...or...,在第二个参数为false时,始终返回c,会出现问题:

a = true
print (a and false or true)

输出结果会是true 而不是三目运算符应该返回的false。
这时候,可以将三目运算符的后面两个部分转换成table,运算结束后再取第一个元素,即可实现:

a = true
b = (a and {false} or {true})[1]
if b then
print("true")
else
print("false")
end

自定义迭代器

自定义迭代器的格式:

for 变量列表 in 迭代函数, 状态变量, 控制变量 do

end

自定义无状态迭代器

function square(iteratorMaxCount, currentNumber)
if currentNumber < iteratorMaxCount then
currentNumber = currentNumber + 1
return currentNumber, currentNumber * currentNumber
end
end

for i, n in square, 3, 0
do
print(i, n)
end

多状态迭代器:
多个状态可以存放在table,因此只需要一个参数即可:

array = {"Google", "Runoob"}

function elementIterator (collection)
local index = 0
local count = #collection

return function ()
index = index + 1
if index <= count then

return collection[index]
end
end
end

for element in elementIterator(array) do
print(element)
end

循环时的goto语句

可以使用goto语句来实现continue:

for i=1, 3 do
if i <= 2 then
print(i, "yes continue")
goto continue
end
print(i, " no continue")
::continue::
print([[i'm end]])
end

元表

Lua可以通过设置元表,定义元方法的方式,改变table的一些行为:

__index元方法,可以修改按索引取值的逻辑。
若__index内容是一个表的话,如果table里没有值,会从元表中对应的索引去取:

t_table = setmetatable({k1 = "v1"}, {__index = {k2 = "v2"}})
print(t_table["k1"])
print(t_table["k2"])
t_table["k2"] = "v3"
print(t_table["k2"])






若__index内容是一个函数,则可以定义返回逻辑:

t_table = setmetatable({}, {__index =
function(t_table, key)
if key == 1 then
return "true"
else
return "false"
end
end
})

print(t_table[1])
print(t_table[2])
print(t_table[3])

t_table = {1, 2, 3}

print(t_table[1])
print(t_table[2])
print(t_table[3])









__newindex元方法,可以修改追加索引时的逻辑

t_table = setmetatable({k1 = "v1"}, {
__newindex =
function(t_table, key, value)
rawset(t_table, key, "\"v" .. value .. "\"")
end
})

t_table["k2"] = 2

print(t_table["k1"])
print(t_table["k2"])






其它的规则:

元表 运算符
__add +
__sub -
__mul *
__div /
__mod %
__unm -(相反数)
__concat ..
__eq ==
__lt <
__le <=

__add和__tostring:

t_table = setmetatable({1, 2, 3}, {__add =
function(t_table, data)
t_table[#t_table + 1] = data
return t_table
end,
__tostring =
function(t_table)
local res = ""
for _, v in pairs(t_table) do
res = res .. v
end
return res
end
})
print(t_table)
print(t_table + 4)





需要注意的是,关系运算符,比较的两端,元表必须相同。如果只有一方有元表,另一方没有,又或者是两方拥有不同的元表,会导致比较报错:

a_metatable =
{
__gt = function(a_table, b_table)
return a_table[1] > b_table[1]
end,
__lt = function(a_table, b_table)
return a_table[1] < b_table[1]
end
}
b_metatable =
{
__gt = function(a_table, b_table)
return b_table[1] > a_table[1]
end,
__lt = function(a_table, b_table)
return b_table[1] < a_table[1]
end
}
a_table = setmetatable({0}, a_metatable)
b_table = setmetatable({1}, b_metatable)
print(a_table<b_table)




重写取反操作

a_metatable =
{
__unm = function(a_table)
local _temp_table = {}
for i = #a_table, 1, -1 do
_temp_table[#a_table + 1 - i] = a_table[i]
end
return _temp_table
end
}
p_metatable =
{
__tostring =
function(a_table)
local res = ""
for _, v in pairs(a_table) do
res = res .. v
end
return res
end
}
a_table = setmetatable({1, 2, 3}, a_metatable)
b_table = setmetatable(-a_table, p_metatable)
print(b_table)

__call比较有意思,可以让table可以变得和函数一样可以执行。因此可以写成如下的极其过分的形式:

function_content =
{
__call = function(a_table, a_data)
print(a_data)
end
}


func_print = setmetatable({}, function_content)
b = func_print(4)

协程

function sleep(n)
local t0 = os.clock()
while os.clock() - t0 <= n do end
end


test_coroutine = coroutine.create(
function()
for i = 1, 10, 1 do
print(i)
sleep(0.1)
coroutine.yield()
end
end
)

function do_cro(co)
while(coroutine.status(co) ~="dead") do
coroutine.resume(co)
end
end

do_cro(test_coroutine)

面向对象

用table实现了类与继承



CClassManager = {}
function CClassManager.ctor(cls, ...)
local this = {}
setmetatable(this, cls)
cls.__index = cls
cls.init(this, ...)
return this
end

function CClassManager.VInit(self, ...)
end

function CClassManager.init(self, ...)
self:VInit(...)
end

function CClassManager.dtor(cls)

end



ClassT = CClassManager:ctor()
function ClassT.VInit(self, word)
self.word = word
end

function ClassT.say(self)
print(self.word)
end

test = ClassT:ctor("B")
test:say()
test:dtor()
test:say()