官网:The Programming Language Lua
在线中文手册:http://manual.luaer.cn
Lua技巧(性能),local/table/string/gc https://segmentfault.com/a/1190000004372649
1.Lua中...可表示可选参数,但是跟arg的区别有些大啊!而且如果在一个函数内同时使用...和arg的话,...有效、arg会变成nil(2014.7.17 看skynet代码时发现,arg在5.1跟5.2貌似有些区别,最好是只在获取命令行参数用arg,获取函数可变参数用...,这样可规避问题。)
function func1(...)
print(type(arg),'->',arg)
for k,v in pairs(arg) do
print(k,v)
end
end
function func2(...)
print(type(...),'->',...)
for k,v in pairs({...}) do
print(k,v)
end
end
func1(1,2,3,4,5)
print(string.rep("-", 20))
func2(1,2,3,4,5)
OUTPUT:
table -> table: 00A6B218
1 1
2 2
3 3
4 4
5 5
n 5
--------------------
number -> 1 2 3 4 5
1 1
2 2
3 3
4 4
5 5
[root@test-22 lua-study]# cat var.lua
local function f(...)
if not ... then print('empty'); return end
local t = {}
for i = 1, select('#',...) do
print('i', i, select(i,...))
t[i] = select(i,...)
end
for k,v in pairs(t) do print(k,v) end
end
f('a', 'b', 'c')
f()
local function f2(a,...)
print('f2 called', a, ...)
end
f2('a', 1, 2, 3)
f2('a', table.unpack({1,2,3})) --unpack的结果全部传入
f2('a', false or table.unpack({1,2,3})) --只取upack的第一个结果
[root@test-22 lua-study]# lua var.lua
i 1 a b c
i 2 b c
i 3 c
1 a
2 b
3 c
empty
f2 called a 1 2 3
f2 called a 1 2 3
f2 called a 1
2.setmetatable会返回被操纵的table
oritable = {}
local a = setmetatable(oritable, {__mode="k"})
print("oritable=", oritable)
print("setmetable(oritable,..) returned:", a)
for k,v in pairs(a) do print(k,v) end
print(string.rep('-',30))
for k,v in pairs(getmetatable(oritable)) do print(k,v) end
:!lua setmetatable.lua
oritable= table: 0x1e4a830
setmetable(oritable,..) returned: table: 0x1e4a830
------------------------------
__mode k
3.保护某个table的metatable不被再次修改:在该table(假设名字为mytable)的元表身上设置__metatable域,这样getmetatable(mytable)就会返回所设置的内容,setmetatable(mytable)会报错
[dongsong@localhost lua-study]$ cat setmetatable.lua
oritable = {}
local a = setmetatable(oritable, {__metatable='hello'})
print("oritable=", oritable)
print("setmetable(oritable,..) returned:", a)
print("getmetatable(oritable) returned:", getmetatable(oritable))
print("setmetatble(oritable,..) again:", setmetatable(oritable, {}))
[dongsong@localhost lua-study]$ lua setmetatable.lua
oritable= table: 0x238a860
setmetable(oritable,..) returned: table: 0x238a860
getmetatable(oritable) returned: hello
lua: setmetatable.lua:6: cannot change a protected metatable
stack traceback:
[C]: in function 'setmetatable'
setmetatable.lua:6: in main chunk
[C]: ?
4.require package.path LUA_PATH
lua 5.1的官方文档 There were substantial changes in function require due tothe new module system.However, the new behavior is mostly compatible with the old,butrequire
gets the path frompackage.path insteadof from LUA_PATH
.
[dongsong@localhost require_test]$ tree -a
.
├── myfile2.lua
├── mypackage
│ └── myfile.lua
└── test.lua
1 directory, 3 files
[dongsong@localhost require_test]$ cat test.lua
function test()
package.loaded['myfile2'] = nil
package.loaded['myfile'] = nil
print(string.rep("=",30))
print("package.path = ", package.path)
print("LUA_PATH = ", LUA_PATH)
local rt,msg = pcall(require, "myfile2")
if type(msg) == 'string' then
local i,j
i,j,msg = string.find(msg, '([^\n]+)')
end
print("require myfile2:", rt, msg)
rt,msg = pcall(require, "myfile")
if type(msg) == 'string' then
local i,j
i,j,msg = string.find(msg, '([^\n]+)')
end
print("require myfile:", rt, msg)
end
test()
LUA_PATH = "/home/dongsong/data/lua-study/require_test/mypackage/?.lua"
test()
LUA_PATH = nil
package.path = package.path .. ";/home/dongsong/data/lua-study/require_test/mypackage/?.lua"
test()
print(string.rep('=',30))
for k,v in pairs(package.loaded) do print(k,v) end
[dongsong@localhost require_test]$
[dongsong@localhost require_test]$ lua test.lua
==============================
package.path = ./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua
LUA_PATH = nil
hello,i am myfile2
require myfile2: true true
require myfile: false module 'myfile' not found:
==============================
package.path = ./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua
LUA_PATH = /home/dongsong/data/lua-study/require_test/mypackage/?.lua
hello,i am myfile2
require myfile2: true true
require myfile: false module 'myfile' not found:
==============================
package.path = ./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua;/home/dongsong/data/lua-study/require_test/mypackage/?.lua
LUA_PATH = nil
hello,i am myfile2
require myfile2: true true
hello,i am myfile
require myfile: true true
==============================
string table: 0xa4d2c0
debug table: 0xa52640
package table: 0xa4db50
_G table: 0xa4b6b0
myfile true
io table: 0xa4f760
os table: 0xa50140
table table: 0xa4cbc0
math table: 0xa51570
coroutine table: 0xa4d600
myfile2 true
dofile() loadfile() require()的区别
dofile()和loadfile()都不做所搜,require根据package.path来做搜索
dofile()编译文件并做执行,重复调用dofile()会重复编译和执行
loadfile()只是编译返回而不做执行,重复调用就重复编译
require()是搜索到文件并编译和执行,重复调用不会重复执行
[dongsong@localhost lua-study]$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> t=loadfile("t")
> t()
stdin:1: attempt to call global 't' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: ?
> t=loadfile("t.lua")
> t()
6
> loadfile("t.lua")()
6
> t=dofile("t.lua")
6
> print(t)
nil
> dofile("t.lua")
6
> require("t.lua")
stdin:1: module 't.lua' not found:
no field package.preload['t.lua']
no file './t/lua.lua'
no file '/usr/share/lua/5.1/t/lua.lua'
no file '/usr/share/lua/5.1/t/lua/init.lua'
no file '/usr/lib64/lua/5.1/t/lua.lua'
no file '/usr/lib64/lua/5.1/t/lua/init.lua'
no file './t/lua.so'
no file '/usr/lib64/lua/5.1/t/lua.so'
no file '/usr/lib64/lua/5.1/loadall.so'
no file './t.so'
no file '/usr/lib64/lua/5.1/t.so'
no file '/usr/lib64/lua/5.1/loadall.so'
stack traceback:
[C]: in function 'require'
stdin:1: in main chunk
[C]: ?
> require("t")
6
> require("t")
>
[dongsong@localhost lua-study]$ cat t.lua
a = {1,2,3,4,5,6}
print(table.getn(a))
require返回值的问题:默认返回true,如果require的lua文件有return,则以其return的值作为require的返回值
[dongsong@localhost skynet]$ cat t.lua
a = {1,2,3,4,5}
print("i am required")
[dongsong@localhost skynet]$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> t=require "t"
i am required
> =t
true
> =package.loaded["t"]
true
>
==============================================================
[dongsong@localhost skynet]$ cat t.lua
a = {1,2,3,4,5}
print("i am required")
return a
[dongsong@localhost skynet]$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> pk=require "t"
i am required
> =pk
table: 0x1427320
> =package.loaded["t"]
table: 0x1427320
> for k,v in pairs(pk) do print(k,v) end
1 1
2 2
3 3
4 4
5 5
5.注意elseif和else if的区别,后者在else下面的chunk里面启了新的if块,需要有与之对应的end
6.ipairs vs pairs
[dongsong@localhost lua-study]$ cat pairs.lua
math.randomseed(os.time())
t = {}
for i = 1,10 do t[i] = i*i end
for i = 1,10 do
local v = math.random(1000)
t[v] = v*v
end
print("ipairs(t):")
print(string.rep('v',30))
for k,v in ipairs(t) do print(k,v) end
print(string.rep('^',30))
print("pairs(t):")
print(string.rep('v',30))
for k,v in pairs(t) do print(k,v) end
print(string.rep('^',30))
[dongsong@localhost lua-study]$
[dongsong@localhost lua-study]$ lua pairs.lua
ipairs(t):
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pairs(t):
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100
580 336400
852 725904
854 729316
678 459684
804 646416
188 35344
346 119716
824 678976
771 594441
511 261121
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7.判断table是否为空
if next(myTable) == nil then
-- myTable is empty
end
参见:http://stackoverflow.com/questions/1252539/most-efficient-way-to-determine-if-a-lua-table-is-empty-contains-no-entries
8.貌似Lua没有类似于 php中的print_r()/var_dump(); python中的pprint.pprint() 这种函数。下面写了个简单的:
[root@test-22 lua-study]# cat pprint.lua
function pprint(var, tostr)
local duplicateTable = {}
local rstr = ''
local function realfunc(var, stack)
local function myprint(...)
rstr = rstr .. string.rep("\t",stack)
for _, s in pairs({...}) do
rstr = rstr .. s
end
end
if type(var) ~= "table" then
if type(var) == 'string' then
myprint(' "'..tostring(var)..'" ')
else
myprint(tostring(var))
end
else
--duplicate detect
if duplicateTable[var] then
myprint(tostring(var))
return
else
duplicateTable[var] = 1
end
--print data
myprint(tostring(var), "\n")
if var.__pprint and type(var.__pprint)=='function' then --把日志按照table返回(每行一个元素)
local tstrs = var:__pprint()
for _, s in pairs(tstrs) do myprint(s,'\n') end
else
myprint("{")
local nilflag = true
for k,v in pairs(var) do
if nilflag then
rstr = rstr .. '\n'
nilflag = false
end
realfunc(k, stack+1)
if type(v) == "table" and next(v) ~= nil then
rstr = rstr .. '=>\n'
realfunc(v, stack+2)
elseif type(v) ~= "table" then
if type(v) == 'string' then
rstr = rstr .. '=>' .. ' "'..tostring(v)..'" '
else
rstr = rstr .. '=>' .. tostring(v)
end
else
rstr = rstr .. '=>' .. tostring(v) .. '{}'
end
rstr = rstr .. '\n'
end
myprint("}")
end
end
end
realfunc(var, 0)
rstr = rstr .. '\n'
if tostr then return rstr else io.write(rstr) end
end
local d = {a=1, b=2, c={1,2,3,4}}
local tmpd = {x=1,y={m=1,n=2}}
d[tmpd] = {1,2,3,4,5,6,7,8,9,{"hello","world"}}
d["hello"] = {}
d["dup"] = d
d[d] = "dup2"
d.xx = {a=111, b=22,
__pprint = function(self)
local t = {}
table.insert(t, string.format('a=%d',self.a))
table.insert(t, string.format('b=%d',self.b))
return t
end
}
print(pprint(d, true))
[root@test-22 lua-study]# lua pprint.lua
table: 0x7f88e70
{
table: 0x7f8bc60
{
"y" =>
table: 0x7f8bca0
{
"m" =>1
"n" =>2
}
"x" =>1
}=>
table: 0x7f8bd30
{
1=>1
2=>2
3=>3
4=>4
5=>5
6=>6
7=>7
8=>8
9=>9
10=>
table: 0x7f892f0
{
1=> "hello"
2=> "world"
}
}
"xx" =>
table: 0x7f89480
a=111
b=22
"c" =>
table: 0x7f8bc20
{
1=>1
2=>2
3=>3
4=>4
}
"b" =>2
table: 0x7f88e70=> "dup2"
"dup" =>
table: 0x7f88e70
"hello" =>table: 0x7f89330{}
"a" =>1
}
9.for迭代. 说白了,for中的表达式返回(函数,状态常量,控制变量),每次循环用“状态常量”和“控制变量”作为参数调用“函数”,返回值赋给变量列表(第一项是下次循环的控制变量)。而多变量赋值和多参数赋值都遵循不足用nil补的原则。
[dongsong@localhost lua-study]$ cat iterator.lua
local function allwords()
local line = io.read() -- current line
local pos = 1 -- current position in the line
return function () -- iterator function
while line do -- repeat while there are lines
local startpos, endpos = string.find(line, "%w+", pos)
if startpos then -- found a word?
pos = endpos + 1 -- next position is after this word
return string.sub(line, startpos, endpos) -- return the word
else
line = io.read() -- word not found; try next line
pos = 1 -- restart from first position
end
end
return nil -- no more lines: end of traversal
end
end
io.input("test.txt")
for word in allwords() do
print(word)
end
[dongsong@localhost lua-study]$ lua iterator.lua
function
NumberOfG
local
count
0
for
n
in
pairs
10.把table当普通c数组使用(PS: 交互模式下用=xx就可以直接打印变量xx,而不是必须用print(),这么简单的事情今天才发现,我了个大擦 2014.5.9)
> t = {}
> table.insert(t, 123)
> t[#t+1] = 456
> = t[1]
123
> = t[2]
456
用#table获取table的普通数组段的大小,这里有个小坑,须慎重!
> =a
table: 0xfa52c0
> for k,v in pairs(a) do print(k,v) end
1 1
2 2
3 3
> a[1] = nil
>
> for k,v in pairs(a) do print(k,v) end
2 2
3 3
> =#a
3
> a = {}
> a[2] = 2
> a[3] = 3
> =#a
0
上述的问题其实是因为table的普通数组部分被扩了,同时说明,普通数组部分的删除操作需要注意:
置nil之后数组部分大小没有改变(用#取到普通数组部分大小、不过用pairs和ipairs却无法遍历到相同数目的元素);
而remove操作不同,它会改变数组部分大小同时会改变key和value的映射
> t={1,2,3,4}
> t
> =t
table: 0x15173e0
> =#t
4
> table.remove(t,2)
> =#t
3
> for k,v in pairs(t) do print(k,v) end
1 1
2 3
3 4
> table.insert(t,10)
> for k,v in pairs(t) do print(k,v) end
1 1
2 3
3 4
4 10
追加于2015.7.29
7849(sxh) 2015-07-29 16:11:56
local a = {}
a[2] = 1
a[3] = 1
a[4] = 1
print(#a)
猜猜这个打印几?
4281(xds) 2015-07-29 16:11:55
0 或者 4
7849(sxh) 2015-07-29 16:12:36
4
7849(sxh) 2015-07-29 16:22:42
它有个规则: 如果key的元素个数大于对应个数幂大小的一半,则生成对应幂长度的数组
a[2] = 2 a[3] = 3
0~1 0个元素 0 > 2^0 / 2 不成立 数组长度0
0~2 1个元素 1 > 2^1 / 2 不成立 数组长度0
0~4 2个元素 2 > 2^2 / 2 不成立 数组长度0
7849(sxh) 2015-07-29 16:23:19
也就是说 # 和中间有没有nil 基本没啥关系
7849(sxh) 2015-07-29 16:23:28
#只是单纯的返回数组部分长度吧
11.垃圾收集,数据清理,释放资源,c++对象析构
http://www.lua.org/manual/5.2/manual.html#2.5.1
local CMD = setmetatable({}, { __gc = function() netpack.clear(queue) end })
12.关于table遍历的问题
The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. You may however modify existing fields. In particular, you may clear existing fields.
也就是说,在遍历过程中不能新增KEY,其他可以随便整
13.Lua date and time
参见 http://www.lua.org/pil/22.1.html
1>os.time(timeTable) 年月日必须指定,其他可选,时分秒默认是12:00:00.
2>os.date("*t",unittime) 得到的table中wday是:周日~周六->1~7
os.date("%w",unixtime)得到的字符串是:周日~周六-> 0~6
3>os.date("*t",unixtime)得到的table中isdst是指是否使用夏时制,第一次了解这个概念,比较有意思(http://zh.wikipedia.org/wiki/%E5%A4%8F%E6%97%B6%E5%88%B6)
[dongsong@localhost lua-study]$ cat weekend.lua
function getWeekZeroTime(time)
local zeros = os.date("return {year = %Y, month = %m, day = %d, week = %w}", time)
local zerot = loadstring(zeros)()
local weekv = zerot.week > 0 and (zerot.week - 1) or 6
zerot.week = nil
zerot.hour = 0 --warning: zerot.hour default 12
return os.time(zerot) - weekv*24*3600
end
function func(time)
local zerot = os.date('*t',time)
for k,v in pairs(zerot) do print(k,v) end
local w = tonumber(os.date('%w',os.time()))
print('%w->week:'..w)
print('*t->week:'..zerot.wday)
w = w>0 and w-1 or 6
--or
--w = (zerot.wday>1) and (zerot.wday-2) or 6
zerot.hour, zerot.min, zerot.sec = 0, 0, 0
return os.time(zerot) - w*24*3600
end
local t = os.time()
print(getWeekZeroTime(t))
print(string.rep('-',30))
print(func(t))
[dongsong@localhost lua-study]$
[dongsong@localhost lua-study]$ lua weekend.lua
1402848000
------------------------------
hour 19
min 43
wday 4
day 18
month 6
year 2014
sec 45
yday 169
isdst false
%w->week:3
*t->week:4
1402848000
14.luarocks(http://luarocks.org/) 类似于python的easy_install
[dongsong@localhost ~]$ luarocks --help
lua: /usr/local/bin/luarocks:3: module 'luarocks.loader' not found:
no field package.preload['luarocks.loader']
no file './luarocks/loader.lua'
no file '/usr/share/lua/5.1/luarocks/loader.lua'
no file '/usr/share/lua/5.1/luarocks/loader/init.lua'
no file '/usr/lib64/lua/5.1/luarocks/loader.lua'
no file '/usr/lib64/lua/5.1/luarocks/loader/init.lua'
no file './luarocks/loader.so'
no file '/usr/lib64/lua/5.1/luarocks/loader.so'
no file '/usr/lib64/lua/5.1/loadall.so'
no file './luarocks.so'
no file '/usr/lib64/lua/5.1/luarocks.so'
no file '/usr/lib64/lua/5.1/loadall.so'
stack traceback:
[C]: in function 'require'
/usr/local/bin/luarocks:3: in main chunk
[C]: ?
[dongsong@localhost ~]$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> =package.path
./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua
> package.path = package.path..";/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua"
> require "luarocks.loader"
[dongsong@localhost ~]$ export LUA_PATH='/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua'
[dongsong@localhost ~]$ echo $LUA_PATH
/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua
[dongsong@localhost ~]$ luarocks --help
LuaRocks 2.1.2, a module deployment system for Lua
NAME
/usr/local/bin/luarocks - LuaRocks main command-line interface
SYNOPSIS
/usr/local/bin/luarocks [--from=<server> | --only-from=<server>] [--to=<tree>] [VAR=VALUE]... <command> [<argument>]
...
如何让lua自己去找到这个库,也就是不用每次都重设lua_path呢?
At start-up, Lua initializes this variable with the value of the environment variable LUA_PATH or with a default path defined in luaconf.h, if the environment variable is not defined. Any ";;" in the value of the environment variable is replaced by the default path.
可见,除了在.bash_profile中设置LUA_PATH环境变量以外,还可以直接把需要追加的路径加到lua的配置文件中:我的机器是/usr/include/luaconf.h
15.luaprofiler(http://luaprofiler.luaforge.net/manual.html) 类似于测试c++程序的google-perftools. 暂时还没实际使用过。
16.print(t) string.format('%s',t) tostring(t) 对于table t, 默认会输出“table address", 这里调用的是元表的__tostring方法,如果改写了这个方法,那么要获取一个table的地址就不容易了(google没找到解决办法,还是Python容易,直接id(t)就行了),所以要想得到地址可以在改写__tostring方法之前用tostring(t)获取后放在t身上。(剑雄客户端middleclass区分同类型粒子的不同实例就是这么干的)
17.Lua 垃圾收集 GC
http://blog.csdn.net/yuanlin2008/article/details/8558103 简明的文章
18.关于pcall和异常传播
对可能有异常的lua函数f使用pcall(f),那么f内出现异常也不会中断程序
如果在lua中调用自己编写的c lib的函数f,而函数内有异常,那么程序会在异常处中断,就算pcall(f)程序还是会中断
19.lua判断空格等空串
[dongsong@localhost lua-study]$ cat emptystr.lua
function isBlank(x)
return not not x:find("^%s*$")
end
print(isBlank(' '))
print(isBlank(' \n'))
print(isBlank('\t '))
print(isBlank('; '))
[dongsong@localhost lua-study]$ lua emptystr.lua
true
true
true
false
20.优先级从高到低 http://www.lua.org/pil/3.5.html
^
not - (unary)
* /
+ -
..
< > <= >= ~= ==
and
or
21.闭包(2015.4.30),跟python类似(参见http://blog.csdn.net/xiarendeniao/article/details/6774520 <item61>),前两天客户端同事在for外面定义变量a,每次给a赋值并为a常见一个button(细节不了解,应该是个闭包用于回调),结果所有button点击时发了相同的数据。下面这个小程序对闭包的解释应该够明了了。
[dongsong@localhost lua-study]$ cat upvalue_test_2.lua
local function func()
local funcs = {}
local a
for index = 1, 5 do
a = index
local function func_enclosing()
io.write(string.format('enclosing func %s %d\n', tostring(func_enclosing), a))
end
table.insert(funcs, func_enclosing)
end
return funcs
end
local funcs = func()
for _, tfunc in pairs(funcs) do
io.write(tostring(tfunc), '\n ')
tfunc()
end
[dongsong@localhost lua-study]$ lua upvalue_test_2.lua
function: 0x13ce160
enclosing func function: 0x13ce160 5
function: 0x13cec60
enclosing func function: 0x13cec60 5
function: 0x13cdd70
enclosing func function: 0x13cdd70 5
function: 0x13ce750
enclosing func function: 0x13ce750 5
function: 0x13ce790
enclosing func function: 0x13ce790 5
22.sleep
linux & windows. cpu消耗大
function Sleep(n)
local t0 = os.clock()
while os.clock() - t0 <= n do end
end
linux
function Sleep(n)
os.execute("sleep " .. n)
end
windows
function Sleep(n)
if n > 0 then os.execute("ping -n " .. tonumber(n + 1) .. " localhost > NUL") end
end
23.热更时获取upvalue
local func = packetHandler[opCodes.G2D_ARENA_CHAR_JOIN]
local isMainThread = false
for index = 1, 10 do
local upname, upvalue = debug.getupvalue(func, index)
if not upname then break end
if upname == 'charIdToRank' and next(upvalue) then isMainThread = true; break end
end
if not isMainThread then print("i'm not main thread"); return end
print("i'm main thread")
--do return end
24.lua bit32 (5.3版不提倡使用) 对于大于32bit的整数高位被清除了
> a = 0x7fffffffffffffff
> =a
9223372036854775807
> =bit32.band(a,0x7ffffffffffffff0)
4294967280
> return bit32.band(0xffffffff,0xfffffff0)
4294967280
25.for 语法制造for作用域之内有效的local变量
[root@test-22 lua-study]# cat fortest.lua
local function test()
local m, n = 1, 1
print(string.format('---m(%s) n(%s)', m, n))
while m < 10 do print(string.format('while m(%s)', m)); m = m+1 end
for n = 1, 10 do print(string.format('for n(%s)', n)) end
print(string.format('---m(%s) n(%s)', m, n))
end
test()
[root@test-22 lua-study]# lua fortest.lua
---m(1) n(1)
while m(1)
while m(2)
while m(3)
while m(4)
while m(5)
while m(6)
while m(7)
while m(8)
while m(9)
for n(1)
for n(2)
for n(3)
for n(4)
for n(5)
for n(6)
for n(7)
for n(8)
for n(9)
for n(10)
---m(10) n(1)
26.对大table中的同一value做多次赋值时,先local出来避免多次hash取值,这应该是常识了,今天(207.5.17)看到其他组居然无视。让我差点以为自己想多了...
[root@test-22 lua-study]# cat hash_profile.lua
local t = {}
local num = 0
local aimk = nil
while num < 100000 do
local k = math.random(1000000)
if not t[k] then
t[k] = {a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8, i=9}
num = num + 1
end
if num == 50000 then aimk = k end
end
local function f1()
t[aimk].a = 11
t[aimk].b = 12
t[aimk].c = 13
t[aimk].d = 14
t[aimk].e = 15
t[aimk].f = 16
t[aimk].g = 17
t[aimk].h = 18
t[aimk].i = 19
end
local function f2()
local tt = t[aimk]
tt.a = 11
tt.b = 12
tt.c = 13
tt.d = 14
tt.e = 15
tt.f = 16
tt.g = 17
tt.h = 18
tt.i = 19
end
local function profile(f)
local external = require'external'
local t1 = external.getTickCount()
for _ = 1, 10000000 do f() end
local t2 = external.getTickCount()
return t2-t1
end
print(string.format('f1 %sms', profile(f1)))
print(string.format('f2 %sms', profile(f2)))
print(string.format('f1 %sms', profile(f1)))
print(string.format('f2 %sms', profile(f2)))
print(string.format('f1 %sms', profile(f1)))
print(string.format('f2 %sms', profile(f2)))
[root@test-22 lua-study]# lua hash_profile.lua
f1 4300ms
f2 2386ms
f1 4300ms
f2 2385ms
f1 4299ms
f2 2386ms