23. 二维数组二维数组
mt = {}mt = {}
for i = 1, N dofor i = 1, N do
mt[i] = {} --mt[i] = {} -- 注意要先定义注意要先定义
for j = 1, M dofor j = 1, M do
mt[i][j] = i * jmt[i][j] = i * j
endend
endend
24. 复制复制 TableTable
LuaLua 的的 tabletable 复制都是引用赋值复制都是引用赋值
即新增一个对即新增一个对 tabletable 的引用的引用
local a = {}local a = {}
local b = a -- alocal b = a -- a 和和 bb 都引用同一个都引用同一个 tabletable
25. 比较比较 TableTable
LuaLua 通过“引用”对通过“引用”对 tabletable 、、 userdatauserdata 和 函数 等和 函数 等
进行比较,只有当他们引用同一个对象时,才视进行比较,只有当他们引用同一个对象时,才视
为相等。为相等。
local a, b = {1}, {1}local a, b = {1}, {1}
a == b -- falsea == b -- false
30. 模块定义模块定义
module(...)module(...) 相当于做了以下的事情:相当于做了以下的事情:
local modname = ... --local modname = ... -- 当前模块名当前模块名
local M = {} --local M = {} -- 定义模块定义模块
_G[modname] = M --_G[modname] = M -- 把模块加到全局变量中把模块加到全局变量中
package.loaded[modname] = M --package.loaded[modname] = M -- 模块已加载成功模块已加载成功
setmetatable(M, {__index = _G}) --setmetatable(M, {__index = _G}) -- 模块可以直接访问所有模块可以直接访问所有
全局变量,相当于全局变量,相当于 module(..., package.seeall)module(..., package.seeall)
setfenv(1, M) --setfenv(1, M) -- 保证在模块内定义和调用的函数都以模块保证在模块内定义和调用的函数都以模块
名为前缀名为前缀
31. 模块加载模块加载
模块加载(模块加载( requirerequire )原理:)原理:
function require(name)function require(name)
if not package.loaded[name] thenif not package.loaded[name] then
local loader = findloader(name)local loader = findloader(name)
if loader == nil thenif loader == nil then
error("unable to load module " .. name)error("unable to load module " .. name)
endend
package.load[name] = truepackage.load[name] = true
local res = loader(name)local res = loader(name)
if res ~= nil thenif res ~= nil then
package.loaded[name] = respackage.loaded[name] = res
endend
endend
return package.loaded[name]return package.loaded[name]
endend
32. 访问模块外的变量访问模块外的变量
11 )) setmetatable(M, {__index = _G}) --setmetatable(M, {__index = _G}) -- 模块可直接访问全局变量模块可直接访问全局变量
22 )) local _G = _G --local _G = _G -- 可通过可通过 _G.abc_G.abc 的方式来调用全局的的方式来调用全局的 abcabc 变量变量
33 )按需加载,例如:)按需加载,例如:
local math = math --local math = math -- 在模块顶部显示的调用在模块顶部显示的调用
(如果是使用(如果是使用 lua5.1lua5.1 的的 modulemodule 函数来创建模块的话函数来创建模块的话
就只能通过这种方式来提供外部访问。)就只能通过这种方式来提供外部访问。)
34. 尽量使用尽量使用 localslocals
for i = 1, 1000000 dofor i = 1, 1000000 do
local x = math.sin(i)local x = math.sin(i)
endend
---- 下面这个快下面这个快 30%30% 左右左右 ::
local sin = math.sinlocal sin = math.sin
for i = 1, 1000000 dofor i = 1, 1000000 do
local x = sin(i)local x = sin(i)
endend
39. 字符串缓冲字符串缓冲
字符串连接可以使用字符串连接可以使用 tabletable 作为缓冲,然后用作为缓冲,然后用 concatconcat 来连接来连接
local s = '';local s = '';
for line in io.lines() dofor line in io.lines() do
s = s .. line .. “n” --s = s .. line .. “n” -- 创建一个新字符串创建一个新字符串 ss ,内存移动,内存移动 ss 这么大这么大
endend
---- 下面这个要快十倍,特别是大文件下面这个要快十倍,特别是大文件
local t = {}local t = {}
for line in io.lines() dofor line in io.lines() do
t[#t + 1] = linet[#t + 1] = line
endend
t[#t + 1] = ''t[#t + 1] = ''
s = table.concat(t, "n")s = table.concat(t, "n")
40. 高效输出高效输出
print(a, b, c)print(a, b, c) 比比 print(a..b..c)print(a..b..c) 更高效更高效
io.write(a, b, c)io.write(a, b, c) 比比 io.write(a..b..c)io.write(a..b..c) 更高效更高效
lualua 还有很多这样的例子,原则是尽量避免创建字符串中间变量还有很多这样的例子,原则是尽量避免创建字符串中间变量
41. 一次性定义一次性定义
---- 定义一个对象并初始化定义一个对象并初始化
a = {}; a.x = 10; a.y = 20a = {}; a.x = 10; a.y = 20
---- 用一次性定义,快用一次性定义,快 60%60%
a = { x = 10, y = 20 }a = { x = 10, y = 20 }
42. TableTable 重用重用
local t = {}local t = {}
for i = 1970, 2000 dofor i = 1970, 2000 do
t[i] = os.time({year = i, month = 6, day = 14})t[i] = os.time({year = i, month = 6, day = 14})
endend
---- 下面的快下面的快 50%50% ,内存也使用更少,内存也使用更少
local t = {}local t = {}
local aux = {year = nil, month = 6, day = 14}local aux = {year = nil, month = 6, day = 14}
for i = 1970, 2000 dofor i = 1970, 2000 do
aux.year = iaux.year = i
t[i] = os.time(aux)t[i] = os.time(aux)
endend