Day15 Lua 的全域环境变数 _G 与 _ENV

上一回在研究 rom/programs/monitor.lua 的过程中
看到一些大写的变数 _G, _ENV
心想,该是来面对它们的时候了!

先说在 Lua 5.1 或之前的版本
当我们宣告一个全域变数的时候,会自动被存入 _G 这个全域的 table

a = 1
b = "2"
function c()
    print(3)
end
print(_G.a)     -- 1  _G["a"] 的语法糖
print(_G.b)     -- 2  _G["b"] 的语法糖
print(_G.c)     -- function: 0x13dc770
_G["c"]()       -- 3

如上述程序码,存取 _G 里面的元素时,已经预设是全域,不必再指定 _G
并且可以透过在 _G 存入新的值,来宣告全域变数

a = 1
print(a)        -- 等同 print(_G.a) 或 print(_G["a"])
_G["d"] = true
print(d)        -- true

而事实上,之前我一直在使用的 Lua 内建函式库
也都会存入 _G 这个大表中,也因此我才可以直接呼叫 table.insert(), io.read(), os.date() 等等

print(io)           -- table: 0x195cff0
print(string)       -- table: 0x1956ac0
print(table)        -- table: 0x19588c0
print(table.insert) -- function: 0x42b750
print(os)           -- table: 0x19598d0
print(os.date)      -- function: 0x4272d0
print(print)        -- function: 0x4215c0 最常用的 print,也是全域函数

限制变数环境 (Lua 5.1)

如果想要让变数环境单纯一点,而不是每次都去更动 _G 大表呢?
Lua 5.1 提供了 setfenv 方法,可以改变函数的环境

x = 1
myEnv = {}
setfenv(1, myEnv)
print(x)            -- 这边会出错,因为全新的环境 myEnv 还没有任何变数或方法,就连 print() 都没有 !

可以用继承来解决,所有原本 _G 的变数与方法都会继承

x = 1
myEnv = {}
setmetatable(myEnv, { __index = _G })
setfenv(1, myEnv)
print(x) 

限制变数环境 (Lua 5.2)

Lua 5.2 开始,加入了新的 _ENV 环境
a = 1 相当於 _ENV['a'] = 1
但是 _G 还是可以使用,只是 _ENV["_G"] 指向了 _ENV
也就是 _ENV["_G"] = _ENV,这是为了相容 Lua 5.1 或更旧的程序码

a = 1
b = 2
print(_ENV.a)
print(_G.b)     -- 相当於 print(_ENV["_G"].b)

此外 setfenv 函数已经废弃,要在 Lua 5.2 自订变数环境
则是需要自行宣告新的 _ENV 如下

a = 1
function myfunc()
    local _ENV = { print = print, myvar1 = 2 }
    myvar2 = false
    print(myvar1)       -- 2
    print(_ENV.myvar2)  -- false
    print(_ENV.a)       -- nil  已经是新的环境变数,所以看不到外面的变数 a
end

myfunc()
print(_ENV.a)           -- 1
print(_ENV.myvar1)      -- nil  看不到在函数内自定义的环境变数

对环境变数的实验与学习先到这里
觉得已经愈来愈清楚 Lua 的整个环境与架构设计
下次来研究 Lua 的 coroutine 函式库


<<:  Day15 Todo List

>>:  人脸辨识-day15 应用层面--1

DAY19 - [JS] 功能扩充 - 纪录花费时间

今日文章目录 需求说明 事前准备 过程纪录 参考纪录 需求说明 在每个ToDoList项目中,纪录...

计算资源及资料的设定03

在上一个章节,我们已经建立了一个Datatstore及Container,也上传资料到Contain...

中华电信 VS 元大台湾50

昨天跟朋友聊到中华电信,想说写篇文章来分析一下众多投资人喜爱的标的。 我後来跟大家询问一下,发现好多...

#1 Entry-Level Front-End Web Development

Before learning the front-end web development, let...

Day02 - GCP 介绍及环境建置

什麽是云端服务 ? 云端服务指的就是将软硬体等资源,放到网际网路上作为服务,使用者只需透过网路,就可...