Lua 用一个名为environment 普通的表来保存所有的全局变量。(更精确的说,Lua
在一系列的environment 中保存他的“global”变量,但是我们有时候可以忽略这种多样
性)这种结果的优点之一是他简化了Lua 的内部实现,因为对于所有的全局变量没有必
要非要有不同的数据结构。另一个(主要的)优点是我们可以像其他表一样操作这个保存
全局变量的表。为了简化操作,Lua 将环境本身存储在一个全局变量_G 中,(_G._G 等
于_G)。例如,下面代码打印在当前环境中所有的全局变量的名字:
for n in pairs(_G) do print(n) end
这一章我们将讨论一些如何操纵环境的有用的技术。

1. 全局变量声明:
    Lua中的全局变量不需要声明就可以使用。尽管很方便,但是一旦出现笔误就会造成难以发现的错误。我们可以通过给_G表加元表的方式来保护全局变量的读取和设置,这样就能降低这种笔误问题的发生几率了。见如下示例代码:

--该table用于存储所有已经声明过的全局变量名
local declaredNames = {}
local mt = {
__newindex = function(table,name,value)
--先检查新的名字是否已经声明过,如果存在,这直接通过rawset函数设置即可。
if not declaredNames[name] then
--再检查本次操作是否是在主程序或者C代码中完成的,如果是,就继续设置,否则报错。
local w = debug.getinfo(,"S").what
if w ~= "main" and w ~= "C" then
error("attempt to write to undeclared variable " .. name)
end
--在实际设置之前,更新一下declaredNames表,下次再设置时就无需检查了。
declaredNames[name] = true
end
print("Setting " .. name .. " to " .. value)
rawset(table,name,value)
end, __index = function(_,name)
if not declaredNames[name] then
error("attempt to read undeclared variable " .. name)
else
return rawget(_,name)
end
end
}
setmetatable(_G,mt) a =
local kk = aa --输出结果为:
--[[
Setting a to 11
lua: d:/test.lua:21: attempt to read undeclared variable aa
stack traceback:
[C]: in function 'error'
d:/test.lua:21: in function <d:/test.lua:19>
d:/test.lua:30: in main chunk
[C]: ?
--]]

2. 非全局的环境:
    全局环境存在一个刚性的问题,即它的修改将影响到程序的所有部分。Lua 5为此做了一些改进,新的特征可以支持每个函数拥有自己独立的全局环境,而由该函数创建的closure函数将继承该函数的全局变量表。这里我们可以通过setfenv函数来改变一个函数的环境,该函数接受两个参数,一个是函数名,另一个是新的环境table。第一个参数除了函数名本身,还可以指定为一个数字,以表示当前函数调用栈中的层数。数字1表示当前函数,2表示它的调用函数(这对写一个辅助函数来改变他们调用者的环境是很方便的),以此类推。见如下代码:

下面这段代码是企图应用setfenv 失败的例子:
a = 1 -- create a global variable
-- change current environment to a new empty table
setfenv(1, {})
print(a)
导致:
stdin:5: attempt to call global `print' (a nil value)
(你必须在单独的chunk 内运行这段代码,如果你在交互模式逐行运行他,每一行
都是一个不同的函数,调用setfenv 只会影响他自己的那一行。)一旦你改变了你的环境,
所有全局访问都使用这个新的表,如果她为空,你就丢失所有你的全局变量,甚至_G,
所以,你应该首先使用一些有用的值封装(populate)她,比如老的环境:

a = 1 -- create a global variable
-- change current environment
setfenv(1, {_G = _G})
_G.print(a) --> nil
_G.print(_G.a) --> 1

现在,当你访问"global" _G,他的值为旧的环境,其中你可以使用print 函数。

你也可以使用继承封装(populate)你的新的环境:
a = 1
local newgt = {} -- create new environment
setmetatable(newgt, {__index = _G})
setfenv(1, newgt) -- set it
print(a) --> 1
在这段代码新的环境从旧的环境中继承了print 和a;然而,任何赋值操作都对新表
进行,不用担心误操作修改了全局变量表。另外,你仍然可以通过_G 修改全局变量:

-- continuing previous code
a = 10
print(a) --> 10
print(_G.a) --> 1
_G.a = 20
print(_G.a) --> 20
当你创建一个新的函数时,他从创建他的函数继承了环境变量。所以,如果一个
chunk 改变了他自己的环境,这个chunk 所有在改变之后定义的函数都共享相同的环境,
都会受到影响。这对创建命名空间是非常有用的机制,我们下一章将会看到。

Programming in lua 环境的更多相关文章

  1. 【Lua学习笔记之:Lua环境搭建 Windows 不用 visual studio】

    Lua 环境搭建 Windows 不用 visual studio 系统环境:Win7 64bit 联系方式:yexiaopeng1992@126.com 前言: 最近需要学习Unity3d游戏中的热 ...

  2. lua 学习 (一 )Mac搭建lua环境和ide

    今天开始学习lua  首先是搭建环境 和 我的hello world 首先 交代一下我用的是 Mac 系统 所以在Mac上安装lua 环境很方便的 lua  Mointain Lion - Lua 5 ...

  3. VS2012+LUA环境搭建

    1 .启动VS2012,选择C++下的"win32"项目类型中的"Win2控制台应用程序" 2.工具——选项——项目和解决方案——VC++目录——可执行程序(C ...

  4. Nginx+lua环境搭建

    其实有点类似WampServer一站式安装包 wget http://openresty.org/download/ngx_openresty-1.7.10.1.tar.gz tar -zxvf ng ...

  5. VS2012配置Lua环境

    1.VS2012配置BabeLua插件 2.VS2012配置Lua 1.VS2012配置BabeLua插件 BabeLua插件简介: 安装方法: 关闭VS2012后直接安装BabeLua插件. 下载地 ...

  6. [Lua]Mac系统上安装Lua环境

    1.下载 Lua语言的官方网站 http://www.lua.org/ 下载最新版本的Lua环境 2.安装 解压下载包lua-5.3.1.tar.gz 打开终端Terminal 使用cd命令进入该目录 ...

  7. Mac 端配置 Lua 环境

    一.设计目的 Lua 是一种轻量级的脚本语言,其目的是为了嵌入到程序中,从而为程序提供灵活的扩展和定制功能. 二.特性 轻量级:编译后仅仅 100 余K,可以很方便的嵌入到程序中. 可扩展:Lua 提 ...

  8. 将C注册到lua环境中使用

    注册到lua的方式有两种,一种是lua解释器,如果支持动态链接,使用动态链接机制,将函数接口编译成动态链接库,然后将动态链接库放到lua的C路径(LUA_CPATH)中,然后在lua文件中直接使用 r ...

  9. ubuntu配置lua环境,并进行c与lua的相互调用

    1.安装lua环境 先查看一下apt可获取的lua版本 我们选择lua5.1版本进行安装 sudo apt install lua5.1 安装完之后测试一下是否安装成功,如果可以正常使用,则lua环境 ...

随机推荐

  1. 当使用VS CODE 时,如果窗口中打开的文件无法识别HTML的话,可以使用以下方法添加要识别的文件类型

    找到该文件并修改\Microsoft VS Code\resources\app\extensions\html\package.json{ "name": "html& ...

  2. Oracle 数据库(oracle Database)Select 多表关联查询方式

    Oracle数据库中Select语句语法及介绍 SELECT [ ALL | DISTINCT ] <字段表达式1[,<字段表达式2[,…] FROM <表名1>,<表名 ...

  3. 学习笔记_Java_day13_JSTL_自定义标签库(9)

    自定义标签 1 自定义标签概述 1.1 自定义标签的步骤 其实我们在JSP页面中使用标签就等于调用某个对象的某个方法一样,例如:<c:if test=””>,这就是在调用对象的方法一样.自 ...

  4. Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法

    Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法 这篇笔记将介绍如何使用Ext.Net GridPanel 中使用Sorter. 默认情况下,Ext.Net GridP ...

  5. Python入门 学习笔记 (一)

    原文地址:http://www.cnblogs.com/lujianwenance/p/5939786.html 说到学习一门语言第一步就是先选定使用的工具(环境).因为本人是个小白,所以征求了一下同 ...

  6. objective-c ios webkit 本地存储local-storage

    我有一个Cocoa / Objective-C的应用程序,它嵌入了一个WebKit的web视图.我需要打开的数据库支持和本地存储.我知道这是可以做到-我有它在Safari中工作-但我无法找到如何设置这 ...

  7. html-----010

    22 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...

  8. Sublime Text使用手记

    1.Package Control 输入python 命令安装,打开控制台输入下方代码运行即可.控制台打开可使用快捷键Ctrl+~ 或菜单栏中View> Show Console,可访问Pack ...

  9. SSL Programming Tutorial

    SSL Programming Tutorial � Table of Contents [ � Index       This section demonstrates the implement ...

  10. 通过telnet使用smtp协议发送邮件

    smtp协议是一个简单的邮件传输协议,利用它我们可以将邮件发送给别人,这里将通过telnet这个程序利用smtp协议从网易向gmail发送一封邮件 网上不少有说使用telnet发送邮件的文章,我也看过 ...