因为_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的更多相关文章

  1. Chapter 14_5 _ENV和load

    load在加载代码块时,通常使用全局环境去初始化代码块的_ENV上值. 然而,load选项的第四个参数给出的值就是供_ENV用的.(loadfile函数参数也是一样) 举一个有关初始化的例子,假如我们 ...

  2. Modern C++ CHAPTER 2(读书笔记)

    CHAPTER 2 Recipe 2-1. Initializing Variables Recipe 2-2. Initializing Objects with Initializer Lists ...

  3. Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- ApiWrapper

    前面两片文章讲解了通过AIDL和Messenger两种方式实现Android IPC.而本文所讲的并不是第三种IPC方式,而是对前面两种方式进行封装,这样我们就不用直接把Aidl文件,java文件拷贝 ...

  4. Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- Messenger

    Messenger类实际是对Aidl方式的一层封装.本文只是对如何在Service中使用Messenger类实现与客户端的通信进行讲解,对Messenger的底层不做说明.阅读Android Prog ...

  5. [转]第四章 使用OpenCV探测来至运动的结构——Chapter 4:Exploring Structure from Motion Using OpenCV

    仅供参考,还未运行程序,理解部分有误,请参考英文原版. 绿色部分非文章内容,是个人理解. 转载请注明:http://blog.csdn.net/raby_gyl/article/details/174 ...

  6. 《深入理解计算机系统》 Chapter 7 读书笔记

    <深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...

  7. 《Linux内核设计与实现》Chapter 3 读书笔记

    <Linux内核设计与实现>Chapter 3 读书笔记 进程管理是所有操作系统的心脏所在. 一.进程 1.进程就是处于执行期的程序以及它所包含的资源的总称. 2.线程是在进程中活动的对象 ...

  8. PRML Chapter 2. Probability Distributions

    PRML Chapter 2. Probability Distributions P68 conjugate priors In Bayesian probability theory, if th ...

  9. PRML Chapter 1. Introduction

    PRML Chapter 1. Introduction 为了防止忘记,要把每章的重要内容都记下来,从第一章开始 2012@3@28 今天又回去稍微翻了一下第一章内容,发现第一次看的时候没有看透,每次 ...

随机推荐

  1. 著名清理软件(CCleaner) 5.24.5841 中文版

    软件名称: 著名清理软件(CCleaner) 软件语言: 多国语言 授权方式: 免费软件 运行环境: Win 32位/64位 软件大小: 5.7MB 图片预览: 软件简介: CCleaner的体积小, ...

  2. js两种生成对象模式(公有成员和成员私有)

    假设有个需求,创建一个book类,有isbn码,书名,作者 :可以对isbn进行数据完整性校验:--js设计模式 <script type="text/javascript" ...

  3. 安卓系统浏览器中select下拉按钮无法弹出选择面板奇怪问题解决

    今天遇到个让人崩溃的问题: 平台: 安卓 4.0 描述: 使用 appcan 开发 hybrid 应用,手机上点击下拉选框按钮无法弹出选择面板. 说明: 发现 webkit 内核 position:f ...

  4. ZentaoPHP

    1.框架文档http://devel.cnezsoft.com/book/zentaophphelp/about-10.html zentaoPHP二次开发文档http://devel.cnezsof ...

  5. 无法启动MYSQL服务”1067 进程意外终止”解决办法

    原文:http://www.111cn.net/database/mysql/48888.htm   本文章主要是总结了各种导致mysql提示无法启动MYSQL服务"1067 进程意外终止& ...

  6. EditText文本中用正则匹配是否包含数字,及判断文本只能是纯汉字或纯字母

    遇到判断EditText中文本,是否为制定格式 EditText et; Button btn; @Override protected void onCreate(Bundle savedInsta ...

  7. A Truthful (1-ɛ)-Optimal Mechanism for On-demand Cloud Resource Provisioning---INFOCOM 2015

    [标题] [作者] [来源] [对本文评价] [why] 存在的问题 [how] [不足] assumption future work [相关方法或论文] [重点提示] [其它]

  8. js 的四种设计模式的优缺点

    原始模式: var Car = new Object; Car.color = "blue"; Car.door = 4; Car.showColor = function() { ...

  9. linux的命令使用记录

    iptables禁止53端口的出包(dns) iptables -A OUTPUT -p udp --dport 53 -j DROP linux查看网络监听端口 netstat -npl 文件复制 ...

  10. angularjs的forEach使用

    最近一直在写angularjs中的http后台数据交互,存在的问题就是数据传输中数据格式的问题,如何将传输过来的数据转化为自己需要的数据.当然如果你会一点后台语言的话,完全可以用在后台把数据转化为需要 ...