2

I would like to set different environments on the same function in Lua 5.1 (luajit):

f = function() print(a) end
b = setfenv(f, { a = 1, print = print })
c = setfenv(f, { a = 2, print = print })

I would like b() and c() to print different numbers

I've hacked a way by creating new function chunks based on string.dump and binds env to it, but is there a better more elegant way ? Alternatively, can a function somehow have different upvalues depending on some condition ?

function bind_env(f, env)
  return setfenv(loadstring(string.dump(f)), env)
end

Thanks!

nehz
  • 2,172
  • 2
  • 23
  • 36
  • 3
    Change environment before every call: `b = function(...) return setfenv(f, b_env_table)(...) end`. Maybe, it would be fast enough ;-) – Egor Skriptunoff Aug 21 '14 at 12:45
  • Cool, a better hack than recompiling chunks :) I initially thought it wouldn't work with coroutines, but I just need to set the env before resume and reset it afterwards. – nehz Aug 21 '14 at 13:48

1 Answers1

1

A function's upvalues are determined by its lexical scope:

function test(a, b)
   function func(x) -- sees x, a and b
       print(a*x+b)
   end
   return func
end

f12 = test(1, 2) -- x+2
f23 = test(2, 3) -- 2x+3

f12(4)
f23(4)

The last two lines print 6 and 11. Technically, test(a,b) returns a different function object for every a, b, but notionally, it returns different closures of the same function (same sequence of bytecodes). So if you had

function func(a)
    return function() print(a) end
end 

you could define a different closure for every a:

b = func(1) -- a=1
c = func(2) -- a=2

However note that b==c is false, but that's probably a good thing.

Oliver
  • 27,510
  • 9
  • 72
  • 103