Lua中_ENV的奇怪行为

有人能解释一下为什么lua 5.3.5会这样吗?

a="global"
local b="local"

function problem(_ENV)
    a="fn_a"
    b="fn_b"
end

problem{}
print(_VERSION)
print("a",a)
print("b",b)

--[[ https://www.lua.org/cgi-bin/demo output:
Lua 5.3
a       global
b       fn_b
]]

为什么_ENV改变后局部变量也能被改变呢?是一个bug还是一个特性?

点赞
用户4687565
用户4687565

你正在使用以下代码创建 upvalue

local b="local"
function problem(_ENV)
    b="fn_b"
end

在解析函数期间,解释器检测到函数引用来自于其内部可见的包围范围之一的局部变量,并因此直接将其链接。对局部变量的访问优先于对 _ENV 中全局变量的查找。如果你将 local b="local" 放在函数定义后面,它将不会被函数调用改变。

2018-11-24 15:18:46
用户1847592
用户1847592

Q: 如何消除所有的 upvalue?

答:

a="global"
local b="local"

-- load() 实际上可以消除所有的 upvalue :-)
no_problem = assert(load[[
    return function (_ENV)
        a="fn_a"
        b="fn_b"
    end
]])()

no_problem{}
print(_VERSION)
print("a",a)  -->  a    global
print("b",b)  -->  b    local
2018-11-24 21:14:03