游戏里面用lua来热更新的 redis的默认方法也是lua(我觉得是因为和nosql很搭)
变量
- 全局变量直接使用的时候为
nil
- 数组下标从0开始(不推荐)
a = {[0]="123","32","23"};
- 支持多返回值,多个同时赋值,只需要一个时候使用哑元
_
- 尽量避免一个下划线开头 大写字母
---[[
可以注销掉块注释type
函数永远返回一个字符串- lua将
false
和nil
视为假,将0
和空字符串视为真 - LUA对于小于1014的数字用双精度没有四舍五入的浮点误差,合法的数字写法:
4
,0.4
,4.58e-3
,0.3e12
,5e 20
- Lua的字符串是只读的,
<ddd>
表达数值转义,[[ ]]
,[===[ ]===]
界定换行字符串,(类似的界定注释) tonumber
,tostring
不成功返回nil
#a
获取字符串a的长度,table.maxn
对于nil更加安全- table永远是匿名的,
a ={},b=a
b保持了一个对于a所指向table的引用 a.x
和a["x"]
是一样的,点作为记录,key暗示任意字符串x - x%1
取整x,y=y,x
交换do end
构成基本块(local
)
I/O
代码语言:javascript复制a = io.read("*number")print(a)
function
notes
- 如果要在函数中间使用return,需要加
do return end
- 可变参数
(...)
, 获取arg
- 尾调用不保留调用者栈,这种情况下不会栈溢出,
goto
(用来编写状态机) - 若将函数返回值作为不是最后一个的表达式,保留第一个返回值
- 如果函数调用在单独的一个圆括号里面,只能返回一个结果
- 函数名只是持有某个函数的变量
- 函数内部变量是一个closure,相当于对象的private variable
example
sort
代码语言:javascript复制table.sort(tb, function(a,b) return (a.name > b.name) end
3-var
代码语言:javascript复制-- 对于and来说第一个操作数为真,返回第二个操作数-- or第一个操作数为假,返回第二个操作数(a and b) or c -- a ? b : c, b不可以为false
unnamed
代码语言:javascript复制foo = function(x) return 2 * x end
递归
需要先定义局部变量
代码语言:javascript复制local fact -- 这一句和下一句要求分开【bug主要在这里】fact = function(n)if n == 0 then return 1else return n * fact(n-1)endendorlocal function fact(n) if n==0 then return 1 else return n * fact(n-1) endend
闭包
内部的函数体可以访问外部函数的局部变量(upvalue)
代码语言:javascript复制domo 重定义限制程序打开文件
do local oldOpen = io.open io.open = function(filename, mode) if access_OK(filename, mode) then return oldOpen(filename, mode) else return nil, "access denied" end endend
局部函数
代码语言:javascript复制-- g can use f herelocal f = function(...)endlocal g = function(...)f()end
递归局部函数
需要先声明
代码语言:javascript复制local factfact = function(n) if n == 0 then return 1 else return n * fact(n-1) endend
tables
代码语言:javascript复制a = {}; a.x = 1;b = {}; b.x = 1;a ~= ba.foo = function(x,y) return x y endunpack(a)-- 分离一层
block
normal
代码语言:javascript复制do local i = 1enddo return end -- 用于调试
if, while, repeat
代码语言:javascript复制if conditions thenelseif conditions thenendwhile condition doendrepeat statements;until conditions;
for
代码语言:javascript复制for var = beg,end,step do -- 如果为表达式一次性求职endfor i,v in ipairs(a)doendfor key in pairs(v)doend-- 死循环for i = 1,math.huge doend
iterator
- 使用闭包实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15function list_iter(t) local i = 0 local n = table.getn(t) return function() i = i 1 if i <= n then return t[i] end end end t = {1,2,3} iter = list_iter(t) while true do local element = iter() if element == nil then break end print(element)
- 范性for本身实现
for <var-list> in <exp-list> do end
- 无状态的迭代器
for i,v in ipairs(a) do end
编译运行
require
会搜索目录加载文件,避免同一个文件- load c 1 2local path = "/xxxx/xxx.so" loacl f= loadlib(path, "luaopen_socket")
错误
抛出
代码语言:javascript复制if n then error("123") endassert(io.read("*number"), "123")
处理
代码语言:javascript复制if n then error("123") endassert(io.read("*number"), "123")
协同程序
Lua将所有关于协同程序的函数放置在一个名为coroutine的table里面
代码语言:javascript复制fco = coroutine.create(f) -- 创建,处于挂起状态coroutine.resume(fco) -- 启动或者再次启动coroutine.status(co) -- suspended/running/dead/normalcoroutine.yield() -- 函数内部挂起,yield(1,2)将返回1,2
非抢占式多线程 管道,迭代器
代码语言:javascript复制fco = coroutine.create(f) -- 创建,处于挂起状态coroutine.resume(fco) -- 启动或者再次启动coroutine.status(co) -- suspended/running/dead/normalcoroutine.yield() -- 函数内部挂起,yield(1,2)将返回1,2
- 第一,加载 LuaSocket 库 require “luasocket”
- 第二,定义远程主机和需要下载的文件名 host = “www.w3.org" file = “/TR/REC-html32.html”
- 第三,打开一个 TCP 连接到远程主机的 80 端口(http 服务的标准端口) c = assert(socket.connect(host, 80)) 上面这句返回一个连接对象,我们可以使用这个连接对象请求发送文件 c:send(“GET “ .. file .. “ HTTP/1.0rnrn”) receive 函数返回他送接收到的数据加上一个表示操作状态的字符串。当主机断开连接时,我们退出循环。
- 第四,关闭连接 c:close()
自定义table参数
代码语言:javascript复制-- t.__tostring = xxx-- set:local mt = { __index = t}setmetatable(proxy, mt) __tostring -- 打印__index -- t[x] getter__newindex -- t[x] setter
全局变量
代码语言:javascript复制_G[x]
局部作用域
代码语言:javascript复制-- 创建a = 1 -- create a global variable -- change current environment setfenv(1, {_G = _G}) _G.print(a) --> nil _G.print(_G.a) --> 1-- 继承a = 1 local newgt = {} -- create new environment setmetatable(newgt, {__index = _G}) setfenv(1, newgt) -- set it print(a) --> 1
面向对象
代码语言:javascript复制function Account:withdraw(v) -- a:withdrawfunction withdraw(self, v) -- a.withdraw(可以互相通用)
- 原表中实现类的方法,算术方法包括:
__add
,__mul
,__sub
,__div
,__unm
,__mod
,__pow
,关系方法包括__eq
,__lt
,__le
- 表中找不到会访问
__index(t,k)
方法,更新为__newindex(t,k,v)
方法 1 2 3 4 5 6 7 8 9 10 11function setDefault(t,d) local mt = {__index=function() return d end} setmetatable(t,mt) end local key = {} -- trick, 唯一索引 local mt = {__index = function(t) return t[key] end} fuction setDefault(t,d) t[key] = d setmetatable(t,mt) end - 新建对象 1 2 3 4 5function c:new(o) o = o or {} setmetatable(o,c) return o end
继承
代码语言:javascript复制function Account:withdraw(v) -- a:withdrawfunction withdraw(self, v) -- a.withdraw(可以互相通用)
weak表
- 如果将一些对象放到一个数组当中,Lua将不会回收他们
- 如果一个对象只有弱引用指向它,那么gc会自动回收该对象的内存。
- weak 表
一个
weak
引用阻止对象被回收,表的weak性由他的metatable
的__mode
域来制定的,k
指key
是weak
,v
指value
是weak
1 2 3 4 5a, b = {}, {} setmetatable(a,b) b.__mode = "k" collectgarbage()
用途: 记忆函数,对象的属性关联
函数工厂
解析
setfenv(f, table):设置一个函数的环境 (1)当第一个参数为一个函数时,表示设置该函数的环境 (2)当第一个参数为一个数字时,为1代表当前函数,2代表调用自己的函数,3代表调用自己的函数的函数,以此类推
标准库
数学
简介
数学库由算术函数的标准集合组成,比如三角函数库(sin, cos, tan, asin, acos, etc.), 幂指函数(exp, log, log10),舍入函数(floor, ceil)、max、min,加上一个变量 pi。数学 库也定义了一个幂操作符(^)。 所有的三角函数都在弧度单位下工作。(Lua4.0 以前在度数下工作。)你可以使用 deg 和 rad 函数在度和弧度之间转换。
random
math.random 用来产生伪随机数,有三种调用方式:
- 第一:不带参数,将产生 [0,1)范围内的随机数.
- 第二:带一个参数 n,将产生 1 <= x <= n 范围内的随机数 x.
- 第三:带两个参数 a 和 b,将产生 a <= x <= b 范围内的随机数 x. math.randomseed(os.time())
table
lua 假定array在最后一个非nil位置结束
代码语言:javascript复制table.getn -- memory searchtable.setntable.insert(a,x) -- pushtable.remove(a) -- poptable.insert(a,1,x), table.remove(a,1)table.sort
string
代码语言:javascript复制string.len(s)string.rep(s,n) -- repeat s for n timesstring.lower(s) -- upperstring.sub(s,i,j) -- begin with 1. end as -1i, j = string.find(s, "hello", [beg pos])s, count = string.gsub(ori, mod, replace[, time])
IO
简单模式/完全模式
代码语言:javascript复制io.input(filename), io.output(filename)io.read() -- a lineio.read(*all)io.read(*number)io.read(*line)io.read(*num) -- char numio.read(0) -- whether EOFio.write("",math.sin(3),"")f = assert(io.open("xxx.xxx", "r"))local lines, rest = f:read(BUFISIZE,"*line")outf:flush
os
代码语言:javascript复制io.input(filename), io.output(filename)io.read() -- a lineio.read(*all)io.read(*number)io.read(*line)io.read(*num) -- char numio.read(0) -- whether EOFio.write("",math.sin(3),"")f = assert(io.open("xxx.xxx", "r"))local lines, rest = f:read(BUFISIZE,"*line")outf:flush
debug
- 栈级别
- HOOK(call, return, line, count)
useful functions
代码语言:javascript复制string.format(fmt.."%q", unpack(arg), "1234")table.sort(tb1, function(a,b) return (a.name>b.name) end)io.read(*all)
(私货)SimpleFramework
既然你看到了最后,不如看下传统热更新框架~~ 1 2 3 4 5 6xxxPanel.prefab, xxx.AssetBundle=>build Windows Resource GlobalGenerator:OnResourceInited->LuaScriptPanel->xxxPanel GameManager.Lua->OnInitOK()->CtrlManager.Init() Define.Lua:"xxx=xxxCtrl" GameManager.Lua:ctrl:Awake() LayerPanel