Programming in lua 环境
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 环境的更多相关文章
- 【Lua学习笔记之:Lua环境搭建 Windows 不用 visual studio】
Lua 环境搭建 Windows 不用 visual studio 系统环境:Win7 64bit 联系方式:yexiaopeng1992@126.com 前言: 最近需要学习Unity3d游戏中的热 ...
- lua 学习 (一 )Mac搭建lua环境和ide
今天开始学习lua 首先是搭建环境 和 我的hello world 首先 交代一下我用的是 Mac 系统 所以在Mac上安装lua 环境很方便的 lua Mointain Lion - Lua 5 ...
- VS2012+LUA环境搭建
1 .启动VS2012,选择C++下的"win32"项目类型中的"Win2控制台应用程序" 2.工具——选项——项目和解决方案——VC++目录——可执行程序(C ...
- Nginx+lua环境搭建
其实有点类似WampServer一站式安装包 wget http://openresty.org/download/ngx_openresty-1.7.10.1.tar.gz tar -zxvf ng ...
- VS2012配置Lua环境
1.VS2012配置BabeLua插件 2.VS2012配置Lua 1.VS2012配置BabeLua插件 BabeLua插件简介: 安装方法: 关闭VS2012后直接安装BabeLua插件. 下载地 ...
- [Lua]Mac系统上安装Lua环境
1.下载 Lua语言的官方网站 http://www.lua.org/ 下载最新版本的Lua环境 2.安装 解压下载包lua-5.3.1.tar.gz 打开终端Terminal 使用cd命令进入该目录 ...
- Mac 端配置 Lua 环境
一.设计目的 Lua 是一种轻量级的脚本语言,其目的是为了嵌入到程序中,从而为程序提供灵活的扩展和定制功能. 二.特性 轻量级:编译后仅仅 100 余K,可以很方便的嵌入到程序中. 可扩展:Lua 提 ...
- 将C注册到lua环境中使用
注册到lua的方式有两种,一种是lua解释器,如果支持动态链接,使用动态链接机制,将函数接口编译成动态链接库,然后将动态链接库放到lua的C路径(LUA_CPATH)中,然后在lua文件中直接使用 r ...
- ubuntu配置lua环境,并进行c与lua的相互调用
1.安装lua环境 先查看一下apt可获取的lua版本 我们选择lua5.1版本进行安装 sudo apt install lua5.1 安装完之后测试一下是否安装成功,如果可以正常使用,则lua环境 ...
随机推荐
- jdk在windows中的配置
1.下载jdk(java developer kit),其内部包含jre(java runtime environment): 安装解压缩到一盘内,如:G:\Program Files\Java: 2 ...
- 关于layoutSubviews以及drawRect方法
首先两个方法都是异步执行.layoutSubviews方便数据计算,drawRect方便视图重绘. layoutSubviews在以下情况下会被调用: 1.init初始化不会触发layoutSubvi ...
- 注册一个比较大小Handlebars
1.显示的数据 var datas = { id:"number" } 2.temp模板 <script id="template" type=" ...
- 使用Eclipse提供的Axis1.x生成WSDL文件以及Server和Client代码
使用Eclipse自带的Axis 1.x来创建一个web service应用的服务端和客户端 Axis 是SOAP WebService协议实现,SOAP实质上是一个基于HTTP POST的请求,以X ...
- 配置nginx的负载均衡
1.1 什么是负载均衡 负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性. 负载均衡,英文名称 ...
- LevelDB windows vs2013 c++编译和测试
引用: (src1) :http://download.csdn.net/detail/flyfish1986/8881263(这里有下载地址) (src2) :http://blog.csdn.ne ...
- IF EXIST: The syntax of the command is incorrect.
Batch 脚本中使用 IF EXIST 语句时,总是提示 The syntax of the command is incorrect. 原始 bat 脚本如下: ECHO OFF SET proj ...
- 关于C++对汉字拼音的处理
直到目前我没有找到比较合适的输入汉字输出拼音的函数,那么根据网上流传的几个源码进行了改编,写成了输入汉字输出拼音的函数.对于此函数不能说强大,但是至少稳定可用,输出结果还没有发现什么错误. 那么下面我 ...
- [翻译][MVC 5 + EF 6] 2:基础的增删改查(CRUD)
原文:Implementing Basic CRUD Functionality with the Entity Framework in ASP.NET MVC Application 1.修改Vi ...
- ECMA5.1中关于encodeURI,decodeURI 和encodeComponentURI,decodeComponentURI的区别
The encodeURI and decodeURI functions are intended to work with complete URIs; theyassume that any r ...