Chapter 14_4 使用_ENV
因为_ENV是一个普通的变量,我们可以像其他变量一样去对它进行赋值和访问。
_ENV = nil
上面的赋值操作,将会使得在它之后的代码块不能直接访问全局变量。不过,对控制你的代码所使用的变量有用处。
local print , sin = pirnt , math.sin
_ENV = nil
print() --> 13
print(sin()) --> 0.42016703682664
print(math.cos()) -- error 访问全局变量都会引发错误
我们可以明确地用_ENV来绕过局部变量的声明。
a = -- global
local a =
print(a) --> 12 (local)
print(_ENV.a) --> 13 (global)
一个主要用途是用它去改变一块代码的环境。一旦你改变了环境,所有的全局访问都会使用这个新的表:
_ENV = {} --把当前环境清空
a = -- 在_ENV里创建一个域
print(a) --> stdin:4 attempt to call global 'print' (a nil value )
可以看到,在调用print的时候提示为nil。说明清空的_ENV里没有了print这样的全局变量。
因此,要做的应该是通过老的_G 把它移植过来。
a = --create a global variable
_ENV = {g = _G } --用旧的_G去改变新环境
a = --在新的_ENV 中创建 a
g.print(a) --> 1
g.print(g.a) --> 15 ,通过g可以在任何地方使用print函数,也可以用_G替代g
在Lua中,_G就是一个普通的名字。只有当Lua在创建一个原始全局表和把它赋为全局变量_G时,它才有了特殊的状态。
Lua其实不关心这个变量的值。但是每当我们要涉及到全局变量时,习惯上都是用它。
另一个要使用你的新环境的方法是用继承。
a =
local newgt = {} --create new environment
setmetatable(newgt , {__index = _G})
_ENV = newget -- set it
print(a) --> 1
在这个代码中,从老的环境里继承了point 和 a 变量。
任何访问都是去访问新的table。无论怎么去访问,修改都不会对老的环境造成影响,除非通过_G去修改它的值。
作为一个普通的变量,_ENV遵循一般的域规则。
在一个chunk块中定义的函数,在访问其他外部变量时,实际会访问_ENV。
_ENV = {_G = _G}
local function foo()
_G.print(a) --compiled as '_ENV._G.print(_ENV.a)'
end
a = --_ENV.a
foo() --
_ENV = {_G = _G,a = }
foo() --
如果我们定义一个新的_ENV局部变量,当在涉及到自由名字时就会用这个新定义的变量。
a =
do
local _ENV = { print = print, a=}
print(a) --
end
print(a) --2 (back to the orignal _ENV)
因此,定义一个带有私有环境的函数不是什么难事。
function factory(_ENV)
return function()
return a --"global" a
end
end
f1= factory{a = }
f2 = factory{a = }
print(f1()) --
print(f2()) --
factory函数创建了一个返回全局变量a的闭合函数。
当创建闭合函数的时候,这可见的_ENV变量就是闭合函数factory的_ENV参数。
因此,闭合函数就会用这个外部变量(作为上值)访问自由名字。
使用这个域规则,可以用一些其他方法操作环境。
比如,可以用几个函数共享一个环境,或者用一个函数去修改被其他函数共享的环境。
Chapter 14_4 使用_ENV的更多相关文章
- Chapter 14_5 _ENV和load
load在加载代码块时,通常使用全局环境去初始化代码块的_ENV上值. 然而,load选项的第四个参数给出的值就是供_ENV用的.(loadfile函数参数也是一样) 举一个有关初始化的例子,假如我们 ...
- Modern C++ CHAPTER 2(读书笔记)
CHAPTER 2 Recipe 2-1. Initializing Variables Recipe 2-2. Initializing Objects with Initializer Lists ...
- Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- ApiWrapper
前面两片文章讲解了通过AIDL和Messenger两种方式实现Android IPC.而本文所讲的并不是第三种IPC方式,而是对前面两种方式进行封装,这样我们就不用直接把Aidl文件,java文件拷贝 ...
- Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- Messenger
Messenger类实际是对Aidl方式的一层封装.本文只是对如何在Service中使用Messenger类实现与客户端的通信进行讲解,对Messenger的底层不做说明.阅读Android Prog ...
- [转]第四章 使用OpenCV探测来至运动的结构——Chapter 4:Exploring Structure from Motion Using OpenCV
仅供参考,还未运行程序,理解部分有误,请参考英文原版. 绿色部分非文章内容,是个人理解. 转载请注明:http://blog.csdn.net/raby_gyl/article/details/174 ...
- 《深入理解计算机系统》 Chapter 7 读书笔记
<深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...
- 《Linux内核设计与实现》Chapter 3 读书笔记
<Linux内核设计与实现>Chapter 3 读书笔记 进程管理是所有操作系统的心脏所在. 一.进程 1.进程就是处于执行期的程序以及它所包含的资源的总称. 2.线程是在进程中活动的对象 ...
- PRML Chapter 2. Probability Distributions
PRML Chapter 2. Probability Distributions P68 conjugate priors In Bayesian probability theory, if th ...
- PRML Chapter 1. Introduction
PRML Chapter 1. Introduction 为了防止忘记,要把每章的重要内容都记下来,从第一章开始 2012@3@28 今天又回去稍微翻了一下第一章内容,发现第一次看的时候没有看透,每次 ...
随机推荐
- Centos 7 系统安装完毕修改网卡名为eth0
从CentOS/RHEL7起,可预见的命名规则变成了默认.这一规则,接口名称被自动基于固件,拓扑结构和位置信息来确定.现在,即使添加或移除网络设备,接口名称仍然保持固定,而无需重新枚举,和坏掉的硬件可 ...
- iOS-延迟操作方法总结
在实际应用中,有时候我们会需要延时执行某些操作,所以我们这里总结了四种延迟操作的方法,并简要分析了每种方法的异同. NSObject的相关方法 第一种方法是使用NSObject类的performSel ...
- openstack私有云布署实践【11.2 计算nova - compute节点配置(办公网环境)】
这里我只使用compute1节点配置为示例,其它节点的配置基本是一样的,只是声明的管理IP不同而已 计算节点 # yum install openstack-nova-compute sysfsu ...
- JavaScriptSerializer返回一条Json,页面获取值问题,数据绑定
一,后台处理数据方法 JavaScriptSerializer serializer = new JavaScriptSerializer(); string js = serializer.Seri ...
- google 技巧
inurl: 用于搜索网页上包含的URL. 这个语法对寻找网页上的搜索,帮助之类的很有用. intext: 只搜索网页部分中包含的文字(也就是忽略了标题,URL等的文字). site: 可以限制你搜索 ...
- canvas烟花-娱乐
网上看到一个释放烟花的canvas案例,很好看哦. 新建文本,把下面代码复制进去,后缀名改为html,用浏览器打开即可. 看懂注释后,可以自己修改烟花的各个效果.我试过让烟花炸成了心型.:-) < ...
- FileReader和FileInputStream的区别
1.FileReader和FileInputStream的区别: FileReader.FileWriter处理的是文本文件. FileInputStream/FileOutputStream是继承I ...
- 用DriverBackUp备份了文件 装好系统后怎么把备份的驱动文件还原
1.打开DriverBackUp 2.菜单栏选择Restore 3.选择open backup file 4.找到备份文件位置,并选择.bki后缀的文件 5.点击"打开" 6.勾选 ...
- @Autowired与 @Resource
@Autowired, @Resource 1.注解类型: Autowired可用于构造器.属性.方法.注解 @Target({ElementType.CONSTRUCTOR, ElementType ...
- Shell学习笔记 ——第二天
1.显示日期 date | cal cal 2010 cal 2 2010 2.改变文件拥有者 chown 3.改变文件权限 chmod 4.显示当前目录 pwd 5.查看文件尾部内容,并 ...