lua中常量的实现及表的深拷贝实现
废话:好久没在这里写博客了。。。主要原因是我买了个域名hanxi.info并在github上搭建了个人博客。。。
lua中默认是没有c中的const常量的,在csdn上找到了一个使用setmetatable。参考http://blog.csdn.net/xiaodan007/article/details/6668015。主要原理就是重载__index方法(相当于get方法)和__newindex方法(相当于set方法)。但是他实现的是不支持表中有表的情况的。
下面是我修改后的代码:
function newConst( const_table ) --生成常量表功能
function Const( const_table )
local mt =
{
__index = function (t,k)
6 if type(const_table[k])=="table" then
7 const_table[k] = newConst(const_table[k])
end
return const_table[k]
end,
__newindex = function (t,k,v)
print("*can't update " .. tostring(const_table) .."[" .. tostring(k) .."] = " .. tostring(v))
end
}
return mt
end local t = {}
setmetatable(t, Const(const_table))
return t
end quan = {a = {[]={}}}
quan.b = quan
t = newConst(quan)
--t.b = 4
print(type(t))
print(quan.b) for k,v in pairs(quan) do
print(k,v)
end
我也就是添加了6,7,8三行代码(刚开始想了半天以为递归了,结果思索了下,不是递归,只是函数的实现形式,调用newConst的次数就是读取表的深度,有环的表也不会出现问题的)。__index函数(看参数可以知道取元素t[k])拿到表的元素,如果元素是表则先将表常量化。__newindex函数(看参数可以知道写元素t[k]=v)是给元素赋值,这里不让它实现赋值操作,直接打印错误提示。
为什么要实现这个常量功能,因为现在的手游项目中使用了lua表存放数值策划表,往往程序写代码时会直接去读取静态数据表,万一不小心把表元素赋值了,那就是把静态数据改了,会导致游戏数据错误的。实现了这个lua常量就不会出现静态数据表被修改了。
但是如果需要复制一份静态数据,然后作为临时数据在游戏逻辑中处理(一个同事就这么用过。。。),把静态数据经过了常量处理就再也不能被修改了,不常量化也不行,中途被修改了就再也还原不了静态数据了。因此就需要实现lua表的深拷贝功能了(默然的表与表之间赋值只是简单的别名而已)。先说下思路吧,实现的效果是:
local B = deepcopy(A,n)
把A拷贝给B,n为拷贝深度。如果n为nil时那就是说要拷贝到底了,这又出现了中有环的问题了,不考虑环的问题可以很简单的递归实现,递归结束标识就是判断n的值。代码就先不写了,晚了洗洗睡吧。下次有时间会贴代码的。。。
网上关于深拷贝表的资料很少。总共在下面几个网站上找到了答案。
http://blog.sina.com.cn/s/blog_49bdd36d0100fdc1.html(集合了带环的table和不带环的table的解决方案)
http://www.coronafaqs.com/how-do-i-copy-a-complex-table-in-lua/(就是上面那个带坏的table的解决方案)
http://lua-users.org/wiki/CopyTable(不带环的table的解决方案,还有一个浅拷贝实现)
https://gist.github.com/Deco/3985043 (牛逼的解决方案,非递归实现,能够处理带环的table)
先给上递归式的代码吧。
function table.deepcopy(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, getmetatable(object))
end
return _copy(object)
end
为啥带环的table用这个函数不会无限递归呢?关键之处在于lookup_table,它记录了所有遍历过的table的副本(新的深拷贝的table),如果出现遍历过的直接返回那个副本。第12行为何有两个_copy,这里用的很巧妙,举个例子吧。
t = {
a = 1,
b = 2,
c = {
x = 1,
y = 2,
z = 3,
}
}
t[t.c] = t
t2 = table.deepcopy(t)
print(t2[t2.c])
如果index没有经过_copy处理,则打印出来的则是nil。为何经过_copy处理一定会是t2.c==t2呢?这也就是第6行判断的效果了,它返回的index就是t2.c(因为t2.c要么就是从第7行返回的,要没是新生成的副本,下次拷贝时还是取得同一个副本)。
接下来看第14行,这行不是我想要的,我的目的是拷贝出一份临时表,这分临时表要去除常量的特性,所以我修改如下
return setmetatable(new_table)
这样也就不保留常量特性了。
lua中使用局部函数的好处是很多的。look_up就用到了这个好处,如果lua不支持局部函数,那就只能将look_up表当做参数传递进去了。我之前实现了不支持环的版本,如下:
function table.deepcopy(t, n)
local newT = {}
if n == nil then -- 默认为浅拷贝。。。
n =
end
for i,v in pairs(t) do
if n> and type(v) == "table" then
local T = table.deepcopy(v, n-)
newT[i] = T
else
local x = v
newT[i] = x
end
end
return newT
end
非递归版本太牛逼了,不做介绍了自己想看源码的去看吧
lua中常量的实现及表的深拷贝实现的更多相关文章
- Lua中metatable和__index的联系
Lua中metatable和__index的联系 可以参考 http://blog.csdn.net/xenyinzen/article/details/3536708 来源 http://blog. ...
- Lua中的weak表——weak table
弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...
- Lua中的weak表——weak table(转)
弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...
- linux 进阶2--C++读取lua文件中的变量、一维表、二维表
lua 语言非常灵活,一般把lua 作为脚本文件,会用C++与之进行交互.最重要的是C++代码能读取到脚本中的变量.一维表.二维表. 这样有些参数就可以在lua文件进行更改,而不用重新更改C++代码. ...
- quick-cocos2dx lua中读取 加密 csv表
我非常想把一些非必需的信息以CSV表的格式保存到客户端,以减少和服务器的通讯,降低压力.于是写了这么一个. 但因为大家觉得这样的话,需要每次登陆时来检测同步这些数据,会减慢登陆速度,于是没有用到. 我 ...
- [译] Closures in Lua - Lua中的闭包
原文:(PDF) . 摘要 一等(first-class)函数是一种非常强大的语言结构,并且是函数式语言的基础特性.少数过程式语言由于其基于栈的实现,也支持一等函数.本文讨论了Lua 5.x用于实现一 ...
- lua中的闭包概念的学习笔记
1.闭包的由来: 个人理解,lua中之所以出现闭包的概念,完全是因为lua中允许函数的嵌套定义,并且在内嵌函数中使用了外包函数中定义的局部变量,例如c.c#就不允许函数的嵌套定义(但是允许函数的嵌套调 ...
- [转][译] Closures in Lua - Lua中的闭包
http://www.cnblogs.com/plodsoft/p/5900270.html?utm_source=tuicool&utm_medium=referral 原文:(PDF) . ...
- lua中基类和“继承机制”
基类:基类定义了所有对于派生类来说普通的属性和方法,派生类从基类继承所需的属性和方法,且在派生类中增加新的属性和方法. 继承:继承是C++语言的一种重要机制,它允许在已定义的类的基础上产生新类. lu ...
随机推荐
- BZOJ3173 TJOI2013最长上升子序列(Treap+ZKW线段树)
传送门 Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input ...
- Robots on a grid(DP+bfs())
链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=25585 Current Server Time: 2013-08-27 20:42:26 Ro ...
- 安装mysql数据库中的技巧、错误排查以及实用命令(持续更新)
针对解压版本5.7.16(博主使用的这个版本.在某些低版本中部分命令失效) 一.初始化data目录(解压版解压后没有data目录) mysqld --initialize-insecure --use ...
- 无线安全专题_破解篇02--kali破解pin码
最近项目有点紧,所以本应该上周发的文章,拖到了本周三,在此说声抱歉.无线安全专题,我打算系统地写六个部分,分别为破解篇,攻击篇,欺骗篇,路由篇,移动篇和蓝牙篇,当然在发布的过程中,可能还会掺杂着发布f ...
- hexo框架-next主题-github搭建个人博客
IT`huhui 的前言录 我在GITHUB的个人站点:http://ithuhui.cn 这里遇到的很多问题都是亲身解决后写的.还有遇到不懂可以邮件M我 在这里要感谢浮生志的博客教程,很多我一开始不 ...
- 设计模式->观察者模式
观察者模式能非常大的减少模块之前的耦合.具体的观察者模式,客官们可以去看<设计模式>或者<Head first设计模式>等之类的书. 在java中,java.util库中封装了 ...
- WPF快速入门系列(2)——深入解析依赖属性
一.引言 感觉最近都颓废了,好久没有学习写博文了,出于负罪感,今天强烈逼迫自己开始更新WPF系列.尽管最近看到一篇WPF技术是否老矣的文章,但是还是不能阻止我系统学习WPF.今天继续分享WPF中一个最 ...
- 帅呆了!ASP.NET Core每秒能处理115万个请求
今天看到一篇英文博文 -- ASP.NET Core – 2300% More Requests Served Per Second,被震撼了!ASP.NET Core每秒能处理115万个请求(是的, ...
- [OpenCV] 4、图像叠加 addWeighted
>_<" 这次主要是图像叠加的基本操作: >_<" cv::addWeighted(imageROI, 1.0, logo, 0.6, 0, imageRO ...
- [汇编] 将字符串里的一个'&'字符换成空格
; multi-segment executable file template. data segment ; add your data here! pkey db "press any ...