2

Can anybody explain why lua 5.3.5 acts this way?

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
]]

Why local variable can be changed after _ENV changed? Is it bug or feature?

2 Answers2

1

Q: How to eliminate all upvalues?
A:

a="global"
local b="local"

-- load() actually eliminates all upvalues :-)
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
Egor Skriptunoff
  • 23,359
  • 2
  • 34
  • 64
  • It illiminates upvalues only inside load block but if I call some other function from load block the behaviour will be the same. It can modify parents state. So only io.popen or special c function that create different lua context can truly separate code. – Sergey Kovalev Nov 27 '18 at 12:09
  • @SergeyKovalev - You can use `load` block inside another `load` block ;-) – Egor Skriptunoff Nov 27 '18 at 14:00
0

You are creating upvalue with the following code:

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

During parsing of the function interpreter detects, that function refers to local variable from one of encompassing scopes that are visible from within the function and thus links it directly. Access to local variables precedes lookup of globals in the _ENV. If you put local b="local" after the function definition, it will not be altered by function calls.

Dimitry
  • 2,204
  • 1
  • 16
  • 24