非全局环境

简介: 非全局环境

Lua 语言中,全局变量并不一定非得是真正全局的。 Lua 语言甚至根本没有全局变量。由于我们在平时不断地使用全局变量,所以一开始听上去这可能很诡异。 Lua 语言竭尽全力地让程序员具有全局变量存在的幻觉。现在,让我们看看 Lua 语言是如何构建这种幻觉的。


提示

这种机制是 Lua5.1Lua5.2 之间改变最大的部分,接下来的讨论基本都不适用与 Lua5.1


首先,让我们忘掉全局变量而从自由名称的概念开始讨论。一个自有名称是指没有关联到显式声明上的名称,即它不出现在对应局部变量的范围内。例如,在下面的代码中, xy 是自由名称,而 z 则不是:

local z = 10
x = y + z


接下来就到了关键的部分: Lua 语言编译器将代码段中的所有自由名称 x 转换为 _ENV.x 。因此,此前的代码段完全等价于:

local z = 10
_ENV.x = _ENV.y + z


但是这里新出现的 _ENV 变量由究竟是什么呢?


我们刚刚才说过, Lua 语言中没有全局变量。因此 _ENV 不可能是全局变量。在这里,编译器实际上又进行了一次巧妙的工作。 Lua 语言把所有的代码段都当做匿名函数。所以, Lua 语言编译器实际上将原来的代码段编译为如下形式:

local _ENV = some value (某些值)
return function (...)
  local z = 10
  _ENV.x = _ENV.y + z
end


也就是说, Lua 语言是在一个名为 _ENV 的预定义上值(一个外部的局部变量, upvalue )存在的情况下编译所有的代码段的。因此,所有的变量要么是绑定到了一个名称的局部变量,要么是 _ENV 中的一个字段,而 _ENV 本身是一个局部变量(一个上值)。


_ENV 的初始值可以是任意的表(实际上也不用一定是表)。任何一个这样的表都被称为一个环境。为了维护全局变量存在的幻觉, Lua 语言在内部维护了一个表用来做全局环境。通常,当加载一段代码时,函数 load 会使用预定义的上值来初始化全局环境。因此,原始的代码等价于:

local _ENV = the global environment (全局环境)
return function (...)
  local z = 10
  _ENV.x = _ENV.y + z
end


上述赋值的结果是,全局环境中的字段 x 得到全局环境中字段 y10 的结果。


咋一看,这可能像是操作全局变量的一种相当拐弯抹角的方式。但是,这种方式比那些更简单的实现方法具有更多的灵活性。


我们先总结一下 Lua 语言中处理全局变量的方式:

  • 编译器在编译所有代码段前,在外层创建局部变量_ENV
  • 编译器将所有自由名称var变换为_ENV.var
  • 函数load或函数loadfile使用全局环境初始化代码段的第一个上值,即Lua语言内部维护的一个普通表。


实际上,这也不是太复杂。


有些人由于试图从这些规则中引申出额外的“魔法”而感到困惑,其实,这些规则并没有额外的定义。尤其是,前两条规则完全是由编译器进行的。除了是编译器预先定义的, _ENV 只是一个单纯的普通变量。抛开编译器,名称 _ENV 对于 Lua 语言来说根本没有特殊含义。类似的,从 x_ENV.x 的转换是纯粹的语法转换,没有隐藏的含义。尤其是,在转换后,按照标准的可见性规则, _ENV 引用的是其所在位置所有可见的 _ENV 变量。


提示

Lua 语言将 _ENV 用于错误信息,以便与能够像报告涉及 global x 的一个错误一样报告涉及变量 _ENV.x 的错误。

目录
相关文章
|
1月前
|
缓存 监控 前端开发
如何确保动态导入的模块被正确加载?
通过以上这些方法的综合运用,可以有效地确保动态导入的模块被正确加载,提高应用的稳定性、性能和用户体验。在实际开发过程中,要根据项目的具体情况和需求,灵活运用这些方法,并不断进行测试和优化。
31 4
|
4月前
|
存储 Kubernetes 监控
软件环境管理问题之不可变环境的定义如何解决
软件环境管理问题之不可变环境的定义如何解决
|
4月前
|
微服务
微服务多机房部署大揭秘:全局单一实例、全局多实例,一文让你彻底解锁!
【8月更文挑战第25天】本文探讨了微服务架构中的多机房部署策略,包括全局单一与多实例、区域及机房多实例等方法,分析了它们在可用性、容错性、扩展性和成本上的差异。示例展示了如何利用AWS CloudFormation实现跨不同机房的微服务部署。这为实际应用场景提供了有价值的参考和指导。
115 2
|
7月前
|
JavaScript 前端开发 网络安全
全局代理与自动代理主要差异与选择
全局代理与自动代理主要差异与选择
288 12
|
数据可视化 Java 开发工具
如何比较同一个项目中不同版本的区别
如何比较同一个项目中不同版本的区别
232 0
|
存储
4.3全局描述符表
4.3全局描述符表
112 0
|
存储 NoSQL 算法
【实战场景一】设计一个分布式环境下全局唯一的信号器
如何正确设计一个分布式环境下全局唯一的信号器?
149 0
|
小程序 JavaScript
【小程序】全局数据共享
【小程序】全局数据共享
247 0
【小程序】全局数据共享
|
Kubernetes 网络协议 API
关于K8s中 pod 资源使用全局、局部限制 的一些笔记
写在前面 分享一些 K8s 中 LimitRange 的笔记 博文内容涉及: LimitRange 简单介绍 LimitRange 资源对象创建使用 准入检查和资源约束的一些 Demo 理解不足小伙伴帮忙指正
506 0
|
C++
配置 C 和 C++ 环境
配置 C 和 C++ 环境
120 0