2

How do two closures share an upvalue? And how does it work?

function print_env()
  print(_ENV) --_ENV is an upvalue
end

function foo()
  _ENV = { print = print, print_env = print_env} --redefine the _ENV upvalue
  print(_ENV) --prints: 0094CF40
  print_env() --prints: 0094CF40
end

When I call print_env() from foo() it prints the _ENV defined in foo(), however since they are different functions shouldn't their closures have different upvalues? So when one function modifies its upvalue the other remains the same. Or is _ENV a special upvalue?

Thanks

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
Tiago Costa
  • 4,151
  • 12
  • 36
  • 54
  • As for me, `foo()` prints two identical lines. All three occurrences of `_ENV` reference to the same upvalue. – Egor Skriptunoff Jul 26 '13 at 01:20
  • @EgorSkriptunoff I tried to run the code using dofile and it does use the same upvalue in both functions. But why does that happen? – Tiago Costa Jul 26 '13 at 08:44
  • I think _ENV in this case is upvalue for chunk not for function. _ENV=... is same as _G._ENV=... You can do local _ENV=... to create upvalue for certain function. – moteus Jul 26 '13 at 09:57
  • Why should different functions have different upvalues? It depends on lexical scope. – Egor Skriptunoff Jul 26 '13 at 10:36

1 Answers1

1

Upvalues are external local variables. Two functions can share upvalues when they use the same external local variables. This is determined by lexical scoping. Furthermore, every chunk sees an external local variable named _ENV, which is used to resolve global names.

lhf
  • 70,581
  • 9
  • 108
  • 149