zoukankan      html  css  js  c++  java
  • Chapter 14_4 使用_ENV

      因为_ENV是一个普通的变量,我们可以像其他变量一样去对它进行赋值和访问。

    _ENV = nil

    上面的赋值操作,将会使得在它之后的代码块不能直接访问全局变量。不过,对控制你的代码所使用的变量有用处。

    local print , sin = pirnt , math.sin
    _ENV = nil 
    print(13)              --> 13
    print(sin(13))         --> 0.42016703682664
    print(math.cos(13))    -- error  访问全局变量都会引发错误

    我们可以明确地用_ENV来绕过局部变量的声明。

    a = 13               -- global
    local a = 12
    print(a)             --> 12 (local)
    print(_ENV.a)        --> 13 (global)

    一个主要用途是用它去改变一块代码的环境。一旦你改变了环境,所有的全局访问都会使用这个新的表:

    _ENV = {}      --把当前环境清空
    a =  1         -- 在_ENV里创建一个域
    print(a)       --> stdin:4 attempt to call global 'print' (a nil value )

    可以看到,在调用print的时候提示为nil。说明清空的_ENV里没有了print这样的全局变量。

    因此,要做的应该是通过老的_G 把它移植过来。

    a = 15  --create a global variable
    _ENV = {g = _G }       --用旧的_G去改变新环境
    a = 1                  --在新的_ENV 中创建 a
    g.print(a)             --> 1
    g.print(g.a)           --> 15 ,通过g可以在任何地方使用print函数,也可以用_G替代g       

    在Lua中,_G就是一个普通的名字。只有当Lua在创建一个原始全局表和把它赋为全局变量_G时,它才有了特殊的状态。

    Lua其实不关心这个变量的值。但是每当我们要涉及到全局变量时,习惯上都是用它。

    另一个要使用你的新环境的方法是用继承。

    a  = 1
    local newgt = {}     --create new environment
    setmetatable(newgt , {__index = _G})
    _ENV = newget        -- set it
    print(a)             --> 1

    在这个代码中,从老的环境里继承了point 和 a 变量。

    任何访问都是去访问新的table。无论怎么去访问,修改都不会对老的环境造成影响,除非通过_G去修改它的值。

    作为一个普通的变量,_ENV遵循一般的域规则。

    在一个chunk块中定义的函数,在访问其他外部变量时,实际会访问_ENV。

    _ENV = {_G = _G}
    local function foo()
        _G.print(a)   --compiled as '_ENV._G.print(_ENV.a)'
    end
    a = 10            --_ENV.a
    foo()             --10
    _ENV = {_G = _G,a = 20}
    foo()             --20

    如果我们定义一个新的_ENV局部变量,当在涉及到自由名字时就会用这个新定义的变量。

    a = 2
    do
        local  _ENV  = { print = print, a=14}
        print(a)       --14
    end
    print(a)           --2  (back to the orignal _ENV)

    因此,定义一个带有私有环境的函数不是什么难事。

    function factory(_ENV)
        return function()
            return a        --"global" a
        end
    end
    f1= factory{a = 6}
    f2 = factory{a = 7}
    print(f1())      --6
    print(f2())      --7

    factory函数创建了一个返回全局变量a的闭合函数。

    当创建闭合函数的时候,这可见的_ENV变量就是闭合函数factory的_ENV参数。

    因此,闭合函数就会用这个外部变量(作为上值)访问自由名字。

    使用这个域规则,可以用一些其他方法操作环境。

    比如,可以用几个函数共享一个环境,或者用一个函数去修改被其他函数共享的环境。

  • 相关阅读:
    如何理解cat的输入输出重定向
    Vagrant网络设置
    Vagrant入门
    设计模式的原则
    单例模式
    LRU 实现缓存
    java注解
    java8---lambda表达式
    JUC--Callable 以及Lock同步锁
    JUC--闭锁 CountDownLatch
  • 原文地址:https://www.cnblogs.com/daiker/p/5857579.html
Copyright © 2011-2022 走看看