lua 5.2 的 _ENV

转载 2016年08月28日 15:51:38

转自:http://blog.codingnow.com/2011/12/lua_52_env.html

lua 5.2 正式发布了,对于 lua 语言本身的修改,重中之重就是对 environment 这个概念的修改。

可以说, 5.1 以前的 environment 已经没有了。environment 对于制造一个安全的沙盒(或是实现 DSL)是一个很重要的语言特性,我以前很喜欢使用,但也很容易用错。这次的修改我认为是一个谨慎的决定,并使得 lua 语言更为精简和严谨了。

我这样理解 5.2 中的 environment 。本质上,lua 取消了原有意义上的 environment 。所以我们可以看到 C Function 不再有环境了。function 、在 lua 中称为 closure ,仅仅只是函数体和 upvalue 的联合体。这简化了 lua 语言本身。全局变量实际上只是一个语法糖,编译时再前面加上了 _ENV. 的前缀。这样,从 load 开始,第一个 chunk 就被加上了_ENV 这个 upvalue ,然后依次传递下去。

这个设计基本可以取代以前使用 getfenv/setfenv 改变函数环境的方法。但是又不完全等价。总体来说,增加了一些限制,但不太容易写出 bug 的代码了。

比如说,现在想给返回一个独立环境的函数,可以这样写:

function foobar(env)
    local _ENV = env
    return function() ... end
end

而以前大约是这样:

function foobar(env)
    return setfenv(function() ...  end, env)
end

这不太看得出好坏,但是如果是一组函数,就有区别了。5.2 中是这样:

function foobar(env)
    local _ENV = env
    local ret = {}
    function ret.foo()
        ...     
    end
    function ret.bar()
        ...
    end
    return ret
end

5.1 的等价代码大约是这样:

function foobar(env)
    local old = getfenv()
    setfenv(1,env)
    local ret = {}
    function ret.foo()
        ...     
    end
    function ret.bar()
        ...
    end
    setfenv(1,old)
    return ret
end

或者这样更函数式一点:

function foobar(env)
    return setfenv(
    function()
        local ret = {}
        function ret.foo()
            ...     
        end
        function ret.bar()
            ...
        end
        return ret
    end , env) ()
end

getfenv/setfenv 更灵活,却更容易出错。

对于制作沙盒来说,我感觉 lua 5.2 会更为鼓励使用 load 这种运行时的编译行为。即一定程度上的鼓励元编程。(因为取消了 setfenv ,所以给了 load 显式的参数来制定给 chunk 一个新的环境)

btw, 这个语言设计变更的同时也增强了函数式编程的性能。因为 lua 现在可以更方便的合并那些有相同 upvalue 的 closure 了。(从前除了 upvalue 还有 environment ,合并行为更为复杂)


12 月 30 日补充:

如果非要类似 setfenv 的功能, 修改一组函数的 _ENV 大概需要这样做了:

function getfuncs()
  local _ENV = _ENV
  local ret = {}
  function ret.foo()
    ...
  end
  function ret.setfenv(env)
    _ENV = env
  end
  return ret 
end

快速掌握Lua 5.3 —— 环境

Q:_G? A:_G是一个普通的”table”,它其中存储了当前运行环境中所有的全局变量。 type(_G) --> table for n in pairs(_G) do print(n)...
  • VermillionTear
  • VermillionTear
  • 2016年02月05日 17:12
  • 1458

LUA5.2版本中提供的位运算

Bitwise Operations This library provides bitwise operations. It provides all its functions inside t...
  • sunning9001
  • sunning9001
  • 2015年06月07日 22:47
  • 1811

php中环境变量$_ENV与getenv

PHP中的$_ENV是一个包含服务器端环境变量的数组。它是PHP中一个超级全局变量,我们可以在PHP 程序的任何地方直接访问它。 $_ENV只是被动的接受服务器端的环境变量并把它们转换为数组元素,你...
  • zhezhebie
  • zhezhebie
  • 2017年05月25日 18:11
  • 1290

【lua5.2技术干货】带你理解_ENV和_G, 不懂的同学来学习吧~

转自: http://tieba.baidu.com/p/2208184626 5.1之前, 全局变量存储在_G这个table中, 这样的操作: a = 1 相当于: _G['a...
  • yuliying
  • yuliying
  • 2015年02月08日 00:33
  • 564

Lua5.3 注册表 _G _ENV

注册表的描述,借用PIL中的一段话:registry 一直位于一个由 LUA_REGISTRYINDEX 定义的值所对应的假索引(pseudo-index)的位置。一个假索引除了他对应的值不在栈中之外...
  • murisly
  • murisly
  • 2015年06月16日 15:13
  • 775

Lua 学习笔记——_ENV和_G

Lua 学习笔记——_ENV和_G最近在学lua5.3 发现里面的_G和_ENV的概念容易混淆,花了点时间理了一下,现在做个笔记以防后面忘记,直接用代码例子说明test_env.lua:local l...
  • fishe_r
  • fishe_r
  • 2017年08月03日 14:08
  • 126

Lua5.3 注册表 _G _ENV

注册表的描述,借用PIL中的一段话: registry 一直位于一个由 LUA_REGISTRYINDEX 定义的值所对应的假索引(pseudo-index)的位置。一个假索引除了他对应的值不在栈中...
  • macalyou
  • macalyou
  • 2015年06月16日 20:53
  • 2400

Lua5.2编译好的动态库静态库

  • 2014年12月09日 10:24
  • 1.15MB
  • 下载

lua5.2 source i need

  • 2010年02月09日 08:50
  • 210KB
  • 下载

Lua_5.2_参考

  • 2014年04月25日 22:28
  • 1.41MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:lua 5.2 的 _ENV
举报原因:
原因补充:

(最多只允许输入30个字)