因为_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. wpf 寻找某个控件下的子控件

    /// <summary> /// 寻找某个控件下的子控件 /// </summary> /// <typeparam name="ChildType" ...

  2. LanSoEditor_common ---android平台的视频编辑SDK

    当前版本是LanSoEditor-v1.4 主要使用在音视频的: 裁剪,剪切,分离,合并,转换,拼接,水印,叠加,混合,转码等场合; 我们是针对android平台对ffmpeg做了硬件加速优化,经过多 ...

  3. 关于高性能javascript 笔记

    最近买了本新书,准备自己吃 狗粮的同时也吃点精神食粮.笔记总结,从现在开始,看我啥时候能看完这本酥,就酱紫, begin:

  4. centos6.5 安装zabbix

    实验说明: 操作系统: CentOS6.5 64位 Web环境: Apache Mysql PHP zabbix版本: LTS 2.2.10 Linux服务器IP: 10.0.0.2 Linux客户端 ...

  5. 洞穴勘测(bzoj 2049)

    Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...

  6. Playmaker 基础使用与案例操作

    首先是把下载好的插件导入Unity工程中. ▼导入完成后第一个动作就是检查下拉菜单里面是否已经增加了Playmaker的功能,如果在安装后没看到Playmaker的菜单,一般情况下直接点击菜单上的空白 ...

  7. 解决 bootstrap 在IE8下的兼容问题

    <meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="v ...

  8. C# Oracle insert 中文乱码

    问题描述: 在PL SQL中insert 中文数据,显示不乱码,通过后台insert的中文数据,显示问号. 解决分三步: 1.Select userenv('language') from dual; ...

  9. @classmethod及@staticmethod方法浅析【python】

    目前对于python中@classmethod 类方法和@staticmethod静态方法的有了一定的认识,之后有进一步的认识后继续记录. @classmethod :是和一个class类相关的方法, ...

  10. css background-attachment属性

    前提是定义了background-image属性,然后用background-attachment来指明背景图的位置是固定于视口的,还是随着包含块移动的.可简单理解为定义背景图片随滚动轴的移动方式. ...