Chapter 15_3 使用环境

  创建模块的基本方法的缺点在于,忘记使用local,很容易就污染全局空间。

“函数环境”是一种有趣的技术,它能够解决上面的问题。就是让模块的主程序块独占一个环境。

这样不仅它的所有函数可以共享这个table,而且它的所有全局变量也都记录在这个table中。还可以将所有的公有函数声明为全局变量。

这样它们就自动地记录在一个独立的table中了。模块所要做的就是将这个table赋予模块名和package.loaded:

local M = {}
_ENV = M
function add (c1,c2)
    return new(c1,r + c2.r, c1.i + c2.i)
end

当我们声明add函数后,它自动就到M.add中去了。在该模块中调用其它函数时,也不再需要前缀,new就会去找M.new。

这样在调用一个导出的函数与一个私有函数就没有任何区别可言。就算忘记写local也不会污染全局命名空间,只会将一个私有函数变成了公有而已。

但是问题来了:我们改变了_ENV环境变量,导致我们无法访问之前的全局变量。

这里有几种方法可以解决(褒贬不一):

1》继承

local M = {}
setmetatable(M,{__index = _G})
_ENV = M

现在module可以直接访问全局标识符,每次访问只需要付出很小的开销。这种方法导致了一个后果,从概念上说,此时的模块中包含了所有的全局变量。

例如,通过该模块调用正弦函数:

complex.math.sin(x)

感觉像有点越界,不受控制了。

2》用局部变量保存旧环境

local M = {}
local _G = _G
_ENV = M        -- or _ENV = nil

此方法必须在所有全局变量的名称前加上"_G",由于没有涉及到元方法,这种访问会比前面的方法快些。

3》只加载需要的模块或函数(以local变量的方式)

--模块设置
local M = {}

-- Import section: 导入段
-- declare everything this module needs from outside
-- 声明这个模块需要从外部引入的所有东西
local sqrt = math.sqrt
local io = io
-- no more external access after this point
--之后就不再需要外部的访问了
_ENV = nil    -- or _ENV = M

这种方法比较正规,但是这种技术要求做更多的工作,但是它能清晰地说明模块的依赖性。

同时,比之前俩个方法运行的速度更快,应为它使用了local 变量。

以上内容来自:《Lua程序设计第二版》和《Programming in Lua  third edition 》

时间: 2024-10-14 19:54:06

Chapter 15_3 使用环境的相关文章

菜鸟笔记 -- Chapter 3.4 环境变量

3.4 Java环境的搭建 工欲善其事必先利其器.在学习Java语言之前,必须了解并搭建好它所需要的开发环境.要编译和执行Java程序,JDK(Java Developers Kits)是必备的.下面将具体认识下JDK和JRE,并进行介绍下载安装JDK和配置环境变量的方法. 3.4.1 Java的跨平台 Java的跨平台是指:通过Java语言编写的应用程序在不同的系统平台上都可以运行.在这里我们要对平台进行一下解读,在菜鸟笔记 Chapter 1 计算机从0讲起中我们知道了OS的出现是为所有的开

信息安全系统设计基础期中总结

Chapter 00 Linux基础 man命令调用手册页 man <command_name> 手册通常被分为8个区段,要查看相应区段的内容,就在 man 后面加上相应区段的数字即可: 1 一般命令 2 系统调用 3 库函数,涵盖了C标准函数库 4 特殊文件(通常是/dev中的设备)和驱动程序 5 文件格式和约定 6 游戏和屏保 7 杂项 8 系统管理命令和守护进程 man有一个-k 选项用起来非常好,这个选项让你学习命令.编程时有了一个搜索引擎,可以举一反三.结合后面学习的grep 命令和

Android 命令行开发入门教程之1

其实,掌握记事本+命令行的编程方式是非常有效的,无论是电脑硬件配置和性能问题的制约,还是对于了解程序内部运行机制.调试等也有很好的帮助.但是很多人因为惧怕或者讨厌使用这种费力的编写习惯也是能够理解的,但这都是表面的现象,后序的工作一样是简单的.可重用的. 其实,掌握记事本+命令行的编程方式是非常有效的,无论是电脑硬件配置和性能问题的制约,还是对于了解程序内部运行机制.调试等也有很好的帮助.但是很多人因为惧怕或者讨厌使用这种费力的编写习惯也是能够理解的,但这都是表面的现象,后序的工作一样是简单的.

Chapter 2 OpenStack基本环境设置

Chapter 2 OpenStack基本环境设置 2.1 实验环境 这里使用虚拟机方式配置OpenStack架构: 首先物理主机安装的操作系统是CentOS6.5 x86_64,使用的虚拟化软件是VMware WorkStation 10 虚拟机网络设置如下: 在物理机上的虚拟网卡的信息如下: vmnet1    Link encap:Ethernet  HWaddr 00:50:56:C0:00:01           inet addr:10.0.0.1  Bcast:10.0.0.25

Chapter 14_3 非全局的环境

关于“环境”的一大问题在于它是全局的,任何对它的修改都会影响程序的所有部分. 例如:若安装一个元表用于控制全局变量的访问,那么整个程序都必须遵循这个规范. 当使用某个库时,没有先声明就使用了全局变量,那么这个程序就无法运行. 在Lua中,全局变量并不需要一定是全局的.甚至可以说Lua没有全局变量. 比如在下面的例子中,var1和var2 就是两个自由名: var1 = var2 + 3 就像之前我们说的,一个自由名不会涉及到一个全局变量,至少不会显示地涉及到. 此外,Lua解释器会把所有的自有名

chapter 14_1 环境

Lua将其所有的全局变量保存在一个常规的table中,称为“global environment”. Lua将环境table自身保存在一个全局变量_G中,_G._G等于 _G . 比如下面的代码打印出_G中所有的全局变量: for n in pairs(_G) do print(n) end 具有动态名字的全局变量 对于访问和设置全局变量,通常赋值操作就可以了.不过,有时也会用到一些元编程的形式. 当操作一个全局变量时,而它的名称却存储在另一个变量中,或者需要通过运行时的计算才能得到. 为了获取

linux(centos)下Java Web环境开发

一.安装jdk 百度搜索jdk,进入http://www.oracle.com/technetwork/java/javase/downloads/index.html找到自己需要版本的jdk的Linux压缩包: 复制出这个压缩包的下载地址(尽量先点击下载,然后在下载的界面复制出资源的链接) 在服务器的合适位置创建一个存放jdk的目录 wget+所复制的jdk下载链接,下载jdk到自己创建的目录中 用mv+原文件名+新文件名,进行文件重命名 tar -xzvf +文件名,进行文件解压 配置jdk

unix环境编程学习-chapter 3 IO读写操作

原子操作pread,pwirte #include <unistd.h> ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);//返回值:读到的字节数,若已到文件结尾则返回0,若出错返回-1 ssize_t pwrite(int fd,const void *buf ,size_t nbytes, off_t offset);//返回值:若成功返回已写的字节数,若出错返因-1 pread,pwirte,相当于顺序调用lse

《linux 内核完全剖析》 chapter 7 初始化程序

初始化程序 7.1 main.c 程序 图中,高速缓存的部分还要扣除显存和ROM BIOS占用的部分.告诉缓冲区是用于磁盘等块设备临时存放数据的地方,以1K字节为一个数据单位. init().函数的功能可分为四个部分 安装根文件系统 显示系统信息 运行系统初始资源配置文件rc中的命令 执行用户登录程序shell程序 要注意的是,由于创建新进程的过程通过完全复制父进程代码段和数据段的方式实现.因此在首次使用fork()创建新进程init时,为了确保新进程用户态栈中没有进程0的多余信息,要求进程0在