https://www.runoob.com/lua/lua-strings.html
逻辑运算
lua只有 nil和false才会判断 false,其余一律判true
print(4 and 5); --> 5
print(nil and 5); --> nil
print(4 or 5); --> 4
print(nil or 5); --> 5
交换
x = 1
y = 2
print(x,y)
x,y = y,x
print(x,y)
作用域
只要没有local 全为 global, 最好都加global和local,区分全局和局部
j = 10 -- global
local i = 1 -- local
global j = 10
local i = 1
只在某一范围生效
do
local a = 1
end
print(a) -- nil
缓存全局
这样查表比较快
local foo = foo
pairs ipairs
pairs是无序的,遍历是随机的
a = {
[5] = "Google",
[4] = "Runoob",
[3] = "Apple",
[1] = "Piano",
[2] = "Guitar" }
for i, v in ipairs(a) do
print(i, v)
end
print("======")
for i, v in pairs(a) do
print(i, v)
end
结果
ipair遇到的nil话
a = {
[5] = "Google",
[4] = "Runoob",
[3] = nil,
[1] = "Piano",
[2] = "Guitar" }
ipairs的底层
ipairs会返回三个值 _f, _s, _var f是函数,s是固定参数,var是变量,var是空 nil结束
自己实现一个ipairs迭代器
local function iter(t, i)
i = i + 1
local v = t[i]
if v then
return i, v
end
return nil
end
local function ipairs_my (a)
return iter, a, 0
end
local a = {"ss", "22", "2312"};
for i,v in ipairs_my(a) do
print(i, v)
end
默认参数
其实就是nil 的话就取后一个
-- 默认参数
local function aaa(n)
return n or 1
end
print(aaa())
可变参数
-- 可变参数
local function aaa(...)
local args = { ... }
for i, v in ipairs(args) do
print(v)
end
print(#args)
end
print(aaa(1,2,3,4,5))
多个返回值
注意不要这样写多个返回值,大坑
-- 多个返回值
local function foo2()
return "a", "b"
end
x,y,z = foo2(),20
print(x,y,z) -- a 20 nil
函数闭包
有点像C# => lambda表达式的写法
-- 函数闭包
local function foo2()
local i = 0
return function()
i = i + 1
return i;
end
end
c1 = foo2()
c2 = foo2()
print(c1())
print(c1())
print(c2())
print(c2())
print(c2())
包 成员函数
-- package 成员函数
MyLib = {}
function MyLib.foo(x,y)
return x + y
end
function MyLib.foo2(x,y)
return x - y
end
print(MyLib.foo(1,2))
print(MyLib.foo2(1,2))
下面这个有点像C++函数指针 和 C#里的委托
local f = function(...)
end
f()
注意 相互引用的话需要单独声明函数指针
错误写法
local fact = function(n)
if n==0 then renturn 1
else return n*fact(n-1) -- buggy
end
end
正确
local fact
fact = function(n)
if n==0 then renturn 1
else return n*fact(n-1) -- buggy
end
end
成员函数的私有化
ddd.lua
local function add()
print("add")
end
local function sub()
print("sub")
end
local function mul()
print("mul")
end
complex = {
add = add,
sub = sub,
}
return complex
test.lua
complex = require "ddd"
complex.sub()
异常处理
local function foo()
error({code = 121})
return 1 / 1
end
local status, err = pcall(foo)
if(status) then
print("success")
else
print("error", err.code)
end
协程
co = coroutine.create(function()
for i = 1, 10 do
print("co", i)
coroutine.yield()
end
end)
coroutine.resume(co)
coroutine.resume(co)
coroutine.resume(co)
coroutine.resume(co)
元表
元表可以改变表的行为模式。
元表有种类class的感觉了
有点像C# JAVA里的 get 和 set
https://www.runoob.com/lua/lua-metatables.html
__index
other = {foo = 4}
t = setmetatable({}, {__index = other})
print(t.foo)
mytable = setmetatable({key1 = "value1"},{
__index = function(mytable, key)
if(key == "key2") then
return "meratablevalue"
else
return nil
end
end
})
print(mytable.key1, mytable.key2)
__newindex
__newindex 元方法用来对表更新,__index则用来对表访问
注意的问题
不能直接return 要 do return end
不能 t[x] 要 t[“x”]
t.os.date("*t")
t.day = t.day + 40
os.date("*t", os.time)
require的模块会在package.loaded表中存在,如果要强制加载模块两次,可以将模块从package.loaded中删除: package.loaded.modname = nil
需要提前算好几次
下面指挥走三次
loca t = {1,2,3}
for i = 1, #t do
t[4] = 4
end
rawget rawset会忽略修改,用自定义的值
值类型是不可以被回收的
瞬表的概念
GC
https://blog.codingnow.com/2018/10/lua_gc.html
-
lua 5.0
- 触发时机 内存变为原来的两倍
- 会停止所有操作,这样会卡
-
lua 5.1
- 步进式收集 (基于内存步进)
- 三色标记法 (白色-不可达 | 灰色-不完全可达 | 黑色-需要保留)
-
lua5.2
- 引入了分代GC
- 垃圾收集器可以集中精力对付刚刚构造出来的年轻对象
-
lua 5.3
- 因为GC有问题 分代被移除
垃圾回收器首次发现某个具有析构器的对象不可达的时候,垃圾回收器把这个对象复苏,并加入到待析构的队列中,析构器执行后,对象就被标记为已析构,当下次垃圾回收发现对象不可达的时候,就把这个对象删掉,所以lua的垃圾回收需要两次调用才会删掉被析构的对象
class类 面向对象
https://blog.codingnow.com/cloud/LuaOO
local _class = {}
function class(super)
local class_type = {}
class_type.ctor = false
class_type.super = super
class_type.new = function(...)
local obj = {}
do
local create
create = function(c, ...)
if c.super then
create(c.super, ...)
end
if c.ctor then
c.ctor(obj, ...)
end
end
create(class_type, ...)
end
-- 跟随子类变化
setmetatable(obj, { __index = _class[class_type] })
return obj
end
local vtbl = {}
_class[class_type] = vtbl
-- 相当于set函数了 绑定所有类型
setmetatable(class_type, { __newindex = function(t, k, v)
vtbl[k] = v
end
})
-- 更新子类
if super then
setmetatable(vtbl, { __index = function(t, k)
local ret = _class[super][k]
vtbl[k] = ret
return ret
end
})
end
return class_type
end
----------------------------------
base_type=class() -- 定义一个基类 base_type
function base_type:ctor(x) -- 定义 base_type 的构造函数
print("base_type ctor")
self.x=x
end
function base_type:print_x() -- 定义一个成员函数 base_type:print_x
print(self.x)
end
function base_type:hello() -- 定义另一个成员函数 base_type:hello
print("hello base_type")
end
--a = base_type.new(2)
--a.hello()
---------------
test = class(base_type)
function test:ctor()
print("test ctor")
end
function test:hello()
print("hello test")
end
a = test.new(1)
a:hello()