Lua将环境本身存储在一个全局变量_G中,(_G._G等于_G)。为了对全局命名空间更好的管理,最好是显示的声明每一个变量,可以通过使用metamethod来改变_G的行为来进行规范:

-- 声明新的变量,使用rawset绕过metamethod的限制
-- 保证声明的变量不为nil,如果声明一个nil变量,等于该变量还是不存在,访问该变量的时候还是会触发__index
declare = function(name, initval)rawset(_G, name, initval or false)
end--改变全局变量的访问行为
setmetatable(_G, {__newindex = function (_, n)error("attempt to write to undeclared variable " ..n, 2)end,__index = function(_, n)error("attempt to read undeclared variable "..n, 2)end,}
)declare("a")
a = 1
print(a)    -- 1
a = nil
print(a)    -- error 触发__index,因为该变量已经释放了

  上述代码中,每一个变量都需要显示declare,并且不能声明nil变量。

  下面这种方法可以声明nil变量,但需要用一个表来显示的记录每一个声明过的变量:

local declareNames = {}
function declare(name, initval)rawset(_G, name, initval)declareNames[name] = true
endsetmetatable(_G, {__newindex = function (t, n, v)if not declareNames[n] thenerror("attempt to write to undeclared var. " ..n, 2)elserawset(t, n, v)endend,__index = function (_, n)if not declareNames[n] thenerror("attempt to read undeclared var. "..n, 2)elsereturn nilendend}
)declare("a")
a = 1
print(a)        -- 1
a = nil
print(a)        -- nil 还是可以访问

  个人偏向于第一种方法,因为第二种方法中,当一个变量被置为nil以后,实际上该变量已经被释放了,所以将变量的置空操作封装在一个undeclear函数中。对第二种方法的改进:

local declareNames = {}
function declare(name, initval)rawset(_G, name, initval)declareNames[name] = true
endfunction undeclare(name)declareNames[name] = nilrawset(_G, name, nil)
endsetmetatable(_G, {__newindex = function (t, n, v)if not declareNames[n] thenerror("attempt to write to undeclared var. " ..n, 2)elserawset(t, n, v)endend,__index = function (_, n)if not declareNames[n] thenerror("attempt to read undeclared var. "..n, 2)elsereturn nilendend}
)declare("a")
a = 1
print(a)        -- 1
undeclare("a")
print(a)        -- error 变量已经不存在了,会触发__index

  两种方法的代价都很小,可以忽略不计,但是给整个编程环境带来的好处是不言而喻的。

转载于:https://www.cnblogs.com/sifenkesi/p/3838311.html

全局变量声明的规范化相关推荐

  1. Python学习笔记——全局变量声明

    最近在编写python程序时发现,在函数中可以对函数外面的全局变量进行读取.打印等操作,但是不能赋值,否则会报错: UnboundLocalError: local variable 'a' refe ...

  2. python在开头声明全局变量_全局变量声明Python

    我有下面的代码片段,可以创建一个笔记并添加到笔记本中. 我的问题与全局变量last_id更相关.当我将它声明为类变量时,即在Class Note中,我得到以下错误但是当我在类外声明时,我的代码工作正常 ...

  3. C++中的全局变量声明和定义

    1.全局变量 全局变量在整个源文件的作用域都是有效的,只需要在一个源文件中定义全局变量,在其他不包含全局变量定义的源文件中用extern关键字再次声明这个全局变量即可. 也可以在一个源文件中定义这个全 ...

  4. [java] java全局变量 声明和定义

    参考:https://blog.csdn.net/lilil371324/article/details/51241580 JAVA全局变量:静态变量,实例变量(即在类体中定义的变量), 静态变量:s ...

  5. JAVA 全局变量 声明与定义

    JAVA全局变量(或称成员变量)可分两种,一种是静态变量,另一种是实例变量,即在类体中定义的变量,有三点得注意: 一.成员变量不能在类体中先声明(定义)后赋值,但静态变量可以先在类体中声明,然后在方法 ...

  6. python声明一个全局变量_全局变量声明Python

    下面的代码创建了一个便条并添加到笔记本中. 我的问题与全局变量last_id更相关.当我将其声明为类变量(即类内注释)时,会得到以下错误,但当我在类外声明时,我的代码可以正常工作. 以下是我的澄清:为 ...

  7. web前端警惕:意料之外的全局变量声明

    在开发中要尽量避免使用全局变量,但是很多基础不扎实的人就可能犯以下这个错误! 错误写法: function fn(){ var a=b=0; } 本以为这是定义了两个局部变量a,b,但结果是a是局部变 ...

  8. c++全局变量的正确声明

    C++中全局变量声明错误情况 造成LNK2005错误主要有以下几种情况:      1.重复定义全局变量.可能存在两种情况:      A.对于一些初学编程的程序员,有时候会以为需要使用全局变量的地方 ...

  9. python 函数内部声明全局变量

    在函数内可以以函数属性的形式声明全局变量: def func1():b = func1.aprint(b) def func2():func1.a = 5 func2() func1() print( ...

最新文章

  1. 属性 visibility
  2. Android实战技巧之十一:Android Studio和Gradle
  3. 上海奋斗记--从3500到700W(转)
  4. Ceres Solver Document学习笔记
  5. linux更改python版本链接
  6. Istio 网关中的 Gateway 和 VirtualService 配置深度解析
  7. 文治者必有武备不然长大了挨欺负_【博古斋·六月春拍】人文事者必有武备
  8. CXF小窥:知道服务器端wsdl地址,如何本地测试服务接口
  9. java 视频 缩略图_如何使用java提取视频缩略图或某一帧的图片
  10. alpine linux安装java,alpinelinux安装openjre
  11. 川大计算机生物学怎么样,四川大学生物信息学初试经验分享
  12. Jmeter系列之接口依赖
  13. STL -- string类字符串
  14. 标题中冒号的用法_英文中冒号的各种用法
  15. 雷达原理---时频分析--6.利用小波分析进行奇异点定位和消除
  16. Galaxian 小蜜蜂
  17. Mac 在指定目录下打开终端的方式
  18. C++ 单词转换例子
  19. 【Android入门】
  20. 戴尔科技云平台赋能“新基建”,打造云底座

热门文章

  1. PEP8 Python 编码规范整理
  2. 精确监听AbsListView滚动至底部
  3. 03:Poor Herobrine 直接插入排序
  4. golang中的strings.IndexRune
  5. 建立索引要考虑的因素
  6. 已解决:Unable to register authentication agent: GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed:
  7. 常考数据结构与算法:判断一个链表是否为回文结构
  8. 怎么对jdk核心包进行跟踪调试,并查看调试中的变量值
  9. ObjC load与initialize 简析
  10. 我是如何用Worktile进行敏捷开发的