lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Soni L. once stated:
> 
> On 27/03/15 11:06 PM, Sean Conner wrote:
> >It was thus said that the Great Tim Hill once stated:
> >>>On Mar 27, 2015, at 2:28 PM, Sean Conner <sean@conman.org> wrote:
> >>>
> >>>  I would expect setting the first upvalue of meta.print() to meta would
> >>>make meta the default global environment for meta.print() and not replace
> >>>the current global environment.
> >>>
> >>Actually, the compiler makes no guarantees about which upvalue (if any)
> >>for a function contains the _ENV environment EXCEPT in the case of the
> >>implicit anonymous function that wraps a compiled chunk. The load() API
> >>family always sets the first upvalue to the environment because it assumes
> >>that the chunk being loaded was a compiled chunk (rather than an explicit
> >>function within a chunk that was accessed with string.dump().
> >   But that isn't the issue.  Even if I got the wrong index, I did not 
> >   expect
> >the global environment to change---only the environment for meta.print().
> >
> >   -spc
>
> You're changing the _value_ of the upvalue and expecting the _upvalue_ 
> to change...

  Then perhaps I have the wrong mental image of how upvalues work in Lua,
because it's doing things I don't expect.

  Okay, explain to me like I'm five how this works.

  I have the following code:

	local a = 3

	function foo(x)
	  local y = 4 * x + a
	  print(y)
	  return y
	end

	foo(3)

  I run it.  I get 15.  Okay, let me change the upvalue "a" [1]

	debug.setupvalue(foo,1,4)
	foo(3)
	print(a)

  And I get 16 (expected) and 4 (also expected).  Now, let's see about
changing the _ENV on that sucker:

	debug.setupvalue(foo,2,{ print = print })
	foo(3)

	lua-53: z.lua:16: attempt to call a nil value (global 'foo')
	stack traceback:
	        z.lua:16: in main chunk
	        [C]: in ?

  WTF? That is NOT what I expected.  Let me think on this ... 

  Okay, it's clear tha upvalues aren't copies of values, but references to
values.  That's why

	debug.setupvalue(foo,1,4)

also changed "a".  So when I do

	debug.setupvalue(foo,2,{ print = print })

I'm changing the default _ENV as well.  

  I won't say that sucks, but it does come across as unintuitive behavior. 
But I will say that having to jump through hoops to change a function's
environment *after it's compiled* sucks [2].

  I also think I've come across a bug in Lua 5.3, but I'll leave that for
another message.

  -spc (Or it could be undefined behavior, I'm not sure ... )

[1]	It's the first upvalue; _ENV is the second upvalue.  I know this
	because of the following code not included in the above:

		info = debug.getinfo(foo,"u")
		for i = 1 , info.nups do
		  name,value = debug.getupvalue(foo,i)
		  print(i,name,value)
		end

	It's consistent between runs.  There you go.

[2]	So how do I get setfenv() in Lua 5.3 again?