快速掌握Lua 5.3 —— "Weak Tables"以及数学库

来源:互联网 发布:上海it外包 编辑:程序博客网 时间:2024/05/20 10:21

Q:“引用”和“引用计数”?

A:“引用”既为对象的名字。比如a = {},名叫a的变量存储的值是一个”table”,”table”的名字是a;同时还可以说变量a存储着”table”的“引用”。
当“(强)引用”被创建时,对象的“引用计数”加1,只要对象的“引用计数”不为0,对象就不会被销毁,Lua的“垃圾回收系统”只回收那些“引用计数”为0的对象。

Q:“强引用”和“弱引用”?

A:当对象被创建时会导致对象的引用计数加1的引用为“强引用”。
默认情况下,Lua中的对象在被创建时都是“强引用”,

-- t中保存了"table"的“强引用”。t = {"one", "two"}-- t保存了新的"table"的“强引用”,原先"table"的引用计数减为0,将被销毁。t = {"three", "four"}

顾名思义,当对象被创建时不会导致对象的引用计数加1的引用为“弱引用”。因为其特性,“弱引用”不会阻止“垃圾回收系统”回收对象。通过”Weak Tables”,Lua支持”table”中的”key”或是”value”或是两者作为“弱引用”存储。
metatable__mode域可以控制具体的操作。这个域必须存储的是一个字符串,如果字符串中包含'k'(一定要是小写的),那么”weak table”中对所有的”key”都使用“弱引用”;如果字符串中包含'v'(小写),那么”weak table”中对所有的”value”都使用“弱引用”,

a = {}b = {}setmetatable(a, b)    -- 将"b"设置为"a"的"metatable"。b.__mode = "k"        -- now 'a' has weak keyskey = {}              -- creates first keya[key] = 1key = {}              -- creates second keya[key] = 2collectgarbage()      -- 强制让Lua回收垃圾。for k, v in pairs(a) do print(v) end    --> 2

这个例子中,第二个key = {}使得变量”key”存储了新的”table”,而原先的”table”没有强引用对其引用了(只有”weak table”对其引用,而且还是弱引用)。所以当调用collectgarbage()时,第一个”table”被垃圾收集器收集,所以”table”中只剩下了第二个”table”(这第二个”table”由变量key对其强引用)。

Q:”weak table”的实际应用?

A:编程中一项通用的技术就是“空间换时间”。为了给函数提速,你可以将函数的参数与其结果作为映射存储起来。当下次有相同的参数时,直接取出结果。
想象一个用Lua写的服务器,他接收请求,请求均是以字符串组成。每一次接收到一个请求,他就调用一次loadstring()loadstring()是一个开销很大的函数,并且有的请求对于服务器来说会非常的频繁,比如closeconnection()。为了避免每次收到这种频繁的请求都要调用一次loadstring(),服务器可以使用一张辅助table来记录请求字符串与其用loadstring()得到的结果之间的映射。在调用loadstring()之前,服务器首先查看请求的命令是否存储在辅助表中,如果存在,则直接取出结果,如果不存在,才调用loadstring(),并在调用完成之后将参数与结果的映射存储在辅助表中。

local results = {}function mem_loadstring (s)  if results[s] then      -- result available?    return results[s]     -- reuse it  else    local res = loadstring(s)   -- compute new result    results[s] = res            -- save for later reuse    return res  endend

这个方案的存储消耗可能是巨大的。尽管如此,它仍然可能会导致意料之外的数据冗余。尽管一些命令一遍遍的重复执行,但有些命令可能只运行一次。渐渐地,这个”table”积累了服务器所有命令被调用处理后的结果,早晚有一天它会挤爆服务器的内存。一个”weak table”提供了对于这个问题的简单解决方案,如果这个结果表中有”weak”值,每次的垃圾收集循环都会移除当前时间内所有未被使用的结果(通常差不多是全部):

local results = {}setmetatable(results, {__mode = "kv"})  -- make keys and values weakfunction mem_loadstring (s)   ...    -- as before

Q:如何使用”weak table”存储”table”的默认值?

A:1、使用”weak table”将”table”与”default value”关联,

local defaults = {}    -- "table"与"default value"之间的映射。setmetatable(defaults, {__mode = "k"})    -- "table"可以被回收。local mt = {__index = function (t) return defaults[t] end}function setDefault (t, d)    defaults[t] = d    setmetatable(t, mt)end

2、使用”weak table”将”default value”与获取”default value”的方法关联,

local metas = {}    -- "default value"与获取"default value"的方法之间的映射。setmetatable(metas, {__mode = "v"})    -- 获取"default value"的方法可以被回收。function setDefault (t, d)    local mt = metas[d]    if mt == nil then        -- 获取"default value"的方法。        mt = {__index = function () return d end}        metas[d] = mt    end    setmetatable(t, mt)end

Q:三角函数、幂函数、对数函数、平方函数、取整取余函数、极值函数、绝对值函数、数值类型函数、无符号数值比较函数、值?

A:

-- 三角函数math.sin(x), math.cos(x), math.tan(x), math.asin(x), math.acos(x), math.atan(x), math.deg(x)    -- 弧度转角度。math.rad(x)    -- 角度转弧度。-- 所有三角函数的参数或者返回值默认是以弧度为单位。如果你想以角度为单位,可以自行转换。local sin, asin, ... = math.sin, math.asin, ...local deg, rad = math.deg, math.radmath.sin = function (x) return sin(rad(x)) endmath.asin = function (x) return deg(asin(x)) end...-- 幂函数、对数函数、平方函数math.exp(x)    -- 返回自然对数"e"的"x"幂。math.log(x [, base])    -- "x"基于"base"的对数,"base"默认是自然对数"e"。math.sqrt(x)    -- 返回"x"的平方根。也可以使用"x ^ 0.5"计算。-- 取整取余函数math.floor(x)    -- 返回小于等于"x"的最大整数。math.ceil(x)    -- 返回大于等于"x"的最小整数。math.modf(x)    -- 返回"x"的整数部分和小数部分。math.fmod(x, y)    -- 返回参数"x / y"的余数。math.tointeger(x)    -- 将"x"转换为整数(如果可以)。-- 极值函数math.max(x, ···), math.min(x, ···)-- 绝对值函数math.abs(x)-- 数值类型函数math.type(x)    -- 如果"x"是数值则返回其类型("integer", "float"),否则返回"nil"。-- 无符号数值比较函数-- 如果整数"m"和"n"以无符号整数形式比较,并且"m < n"则返回"true",否则返回"false"。 math.ult(m, n)-- 值math.pi    -- 圆周率。math.maxinteger    -- 整数的最大值。math.huge    -- C语言中定义的宏"HUGE_VAL"的值,一个大于任何数值的数(数值太大,无法表示时使用)。math.mininteger    -- 整数的最小值。

Q:如何使用随机数?

A:

--[[ 产生伪随机数,有三种调用方式:     1、不带参数,将产生"[0,1)"范围内的随机数。     2、带一个参数"m",将产生"[1, m]"范围内的随机数。     3、带两个参数"m"和"n",将产生[m, n]范围内的随机数。]]math.random([m [, n]])math.randomseed(x)    -- 设置随机数种子。

附加:

1、Lua使用“引用计数”机制供“垃圾回收系统”自动回收无用的垃圾。Lua的“垃圾回收系统”将你从内存管理的负担中解放出来,更重要的是你不用担心与内存管理相关的”bugs”,比如野指针和内存泄露。
但即使是“最聪明”的“垃圾回收系统”也不可能让程序员完全不用关注内存管理的问题。“垃圾回收系统”只能收集他所认为的垃圾,他不知道你所认为的垃圾有哪些。一个典型的例子是栈,当你使用一个数组加上一个存储栈顶索引的变量实现一个栈时,你知道数组中从栈底到栈顶之间的数据是有效的,但Lua不知道。当你pop一个数据,然后将栈顶索引减1的时候,刚被pop的数据依旧在数组中,而你知道他没用了,可是Lua不知道。类似的,任何存储在全局变量中的数据对于Lua来说都不是垃圾(即使有可能你的程序不会再使用它们)。在这两种情况下,这取决于你(的程序)将这些变量赋值为nil
2、要注意,只有对象才可以从一个”weak table”中被收集。比如数字或字符串都是不会被收集的。此外Lua中的函数也是对象,他如果作为”weak table”中的”key”也可以被收集,

a = {}b = {}setmetatable(a, b)    -- 将"b"设置为"a"的"metatable"。b.__mode = "k"        -- now 'a' has weak keysa[1] = 6a["a" .. "b"] = 7foo = function() print() end    -- first key, ignore "print()".a[foo] = 9foo = function() print() end    -- second key, ignore "print()".a[foo] = 10collectgarbage()      -- 强制让Lua回收垃圾。for k, v in pairs(a) do io.write(v, " ") end    --> 6 10 7print()

关于字符串的一些细微差别:从上面的例子来看,尽管字符串是可以被收集的,但他
们仍然跟其他可收集对象有所区别。其他对象,比如”tables”和函数,他们都是显式的被创建。比如,不管什么时候当Lua遇到{}时,它建立了一个新的”table”;任何时候遇到function() ... end时,建立了一个新的函数(实际上是一个”Closure”)。
然而,当Lua见到"a" .. "b"时会创建一个新的字符串?如果系统中已经有一个字符串"ab"的话怎么办?Lua会重新建立一个新的?编译器可以在程序运行之前创建字符串吗?这无关紧要:这些是实现的细节。因此,从程序员的角度来看,字符串是值而不是对象。所以,就像数值或布尔值,一个字符串不会从”weak tables”中被移除(除非它所关联的”vaule”被收集)。
3、math.randomseed()的参数一般为os.time()以产生随机的种子,

math.randomseed(os.time())
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 高二美术生集训时文化课怎么办 唯品会不支持7天无理由退货怎么办 sy来4am了孤存怎么办 淘宝网买的电器坏了怎么办 在闲鱼上买的电器是坏的怎么办 打开时全屏不知变成小屏怎么办 苹果6s原装数据线不充电怎么办 vivo手机安卓系统耗电快怎么办 电视机机顶盒插了电源开不了怎么办 苹果手机更新系统后老是闪退怎么办 16g苹果6s手机内存不足怎么办 苹果以前浏览器页面忽然没了怎么办 白衬衣被别的衣服染了怎么办 把宝贝标题改了没访客了怎么办 微信公众号看不到评论时间了怎么办 微店退款退货买家发空快递怎么办 微信二维码收款顾客少付款了怎么办 江西高考二本差5分上线怎么办 湖南文科考生二本上线差两分怎么办 在商场试鞋自己鞋子被偷怎么办 网易账号忘记密码更换手机了怎么办 一人在外地钱花光了怎么办 银行卡被公安冻结卡里的钱怎么办 在店铺不上班了押工资了怎么办? 在银座的押金拿不出来怎么办 唯品会退货时快递单号填错了怎么办 天猫店铺快递已发到不了怎么办 中邮消费贷没审核通过怎么办 房贷扣款日忘存钱了怎么办 农业银行卡输密码次数超限载怎么办 农业银行卡丢了不知道卡号怎么办 银行卡短信扣费失败怎么恢复怎么办 歌华有线遥控器点了tvav怎么办 一级注册结构延续注册晚了怎么办 在京东买的黄金项链买贵了怎么办 京东上面买的商品不符合实际怎么办 在京东买东西卖家迟迟不发货怎么办 淘宝商家买的货一直不到怎么办 国美买的格力空调发票丢了怎么办 国美实体店发票丢了怎么办 我在苏宁买的冰箱发票丢了怎么办