Jump to content




Function environments

lua help

  • You cannot reply to this topic
9 replies to this topic

#1 KaoS

    Diabolical Coder

  • Members
  • 1,510 posts
  • LocationThat dark shadow under your bed...

Posted 16 March 2013 - 05:14 PM

Hi pros, I have been fiddling a lot with environments and their uses and have run into a bit of a roadblock... it seems like local vars OUTSIDE a function override its environment.

function test()
  print(a)
end

is a basic function, if I call test() it will print nil. then if I say
setfenv(test,{a="testmessage",print=print})
and call the function again it will print "testmessage" which makes sense however if I say
local a="defaultmessage"
function test()
  print(a)
end
setfenv(test,{a="testmessage",print=print})
and call test() it will print "defaultmessage" when a="testmessage" in that function

does anyone know why this is, if it should be like that and if there is a way to correct it?

Edited by KaoS, 16 March 2013 - 06:09 PM.


#2 JokerRH

  • Members
  • 147 posts

Posted 17 March 2013 - 01:06 AM

They are both in the same fenv. I don't know if they actually overwrite each other, but if lua has a local and a normal variable it's going to use the local first.
But since they both have the same variable name, check it like this:
for ind, param in pairs(getfenv()) do print(ind) end
If the variable has been overwritten, it should appear if you run this function.
Otherwise: remove the local and it should work

#3 KaoS

    Diabolical Coder

  • Members
  • 1,510 posts
  • LocationThat dark shadow under your bed...

Posted 17 March 2013 - 01:31 AM

they shouldn't be in the same fenv though because I setfenv it a new environment which replaces the old one, all vars should have to be in the environment to work which is why I have to include print=print in the fenv or it will not have the print command...

if I run that function (I have to add getfenv and pairs to the env to run it in the function though) it prints

a
print
getfenv
pairs

#4 JokerRH

  • Members
  • 147 posts

Posted 17 March 2013 - 01:58 AM

Maybe try it like this:
function func()
  a = "defaultmessage"

  function test()
    print(tostring(a))
  end
end

--Set a new enviroment and run the function
local env = setmetatable({}, {__index = _G})
setfenv(func, env)
func()
--> env.a = "defaultmessage"

env.a = "testmessage"
env.test()


#5 immibis

    Lua God

  • Members
  • 1,033 posts
  • LocationWellington, New Zealand

Posted 17 March 2013 - 02:02 AM

Local variables aren't stored in the environment. They take precedence over global variables with the same name.

#6 lieudusty

  • Members
  • 419 posts

Posted 17 March 2013 - 04:28 AM

I think its because a is a local variable and lua uses the local variable over the global one. (I'm just guessing :P)

#7 JokerRH

  • Members
  • 147 posts

Posted 17 March 2013 - 04:34 AM

View Postlieudusty, on 17 March 2013 - 04:28 AM, said:

I think its because a is a local variable and lua uses the local variable over the global one. (I'm just guessing :P)
Already posted :P

View PostJokerRH, on 17 March 2013 - 01:06 AM, said:

They are both in the same fenv. I don't know if they actually overwrite each other, but if lua has a local and a normal variable it's going to use the local first.

Anyways, @Kaos: I think it should be because it doesn't accept the new enviroment. Sounds weird, haven't fully understood that, too, but if you have the function and you set the new enviroment, the functions inside the function still remain their old fenv, therefor there is still the local a. (Even though you overwrote the fenv)

Edit: Just wrote a little programm that will explain it to you. Copy and paste it to a file and run it and it should give you an idea of what is the problem...
Spoiler


#8 KaoS

    Diabolical Coder

  • Members
  • 1,510 posts
  • LocationThat dark shadow under your bed...

Posted 17 March 2013 - 08:32 AM

View Postimmibis, on 17 March 2013 - 02:02 AM, said:

Local variables aren't stored in the environment
are they not even linked to it in any way? otherwise how does a local var in a function remain local to that function? seems... unintuitive


View Postlieudusty, on 17 March 2013 - 04:28 AM, said:

I think its because a is a local variable and lua uses the local variable over the global one. (I'm just guessing :P)
you are correct in that however in my personal (and I realize unimportant) opinion if they are not in the function then they should be part of the global program's fenv and inherited by the function, if you change the fenv they should no longer inherit


View PostJokerRH, on 17 March 2013 - 01:58 AM, said:

Maybe try it like this:
function func()
  a = "defaultmessage"

  function test()
	print(tostring(a))
  end
end

--Set a new enviroment and run the function
local env = setmetatable({}, {__index = _G})
setfenv(func, env)
func()
--> env.a = "defaultmessage"

env.a = "testmessage"
env.test()
that would work perfectly... the issue is local vars though

anyways I think I have my answer... Lua local vars are not linked to the fenv, it is just how it works and must be accepted

#9 JokerRH

  • Members
  • 147 posts

Posted 17 March 2013 - 10:44 AM

View PostKaoS, on 17 March 2013 - 08:32 AM, said:

they should be part of the global program's fenv and inherited by the function, if you change the fenv they should no longer inherit

You didn't change the fenv. I posted some code above that should have underlined that.
(It's the spoiler)
Lua acts strange it that thing... :D

#10 KaoS

    Diabolical Coder

  • Members
  • 1,510 posts
  • LocationThat dark shadow under your bed...

Posted 17 March 2013 - 05:06 PM

trust me... I do. I understand your example however yours will never work because you need to change the fenv on env.a1 not a, env.a1 inherits the fenv from a BUT it stops doing so when you change a's fenv. check this example

function a()
myvar="hi"
function b()
  print(myvar)
end
end
a()
b()
getfenv(a).myvar="me"
b()
will print "hi" and then "me" HOWEVER
function a()
myvar="hi"
function b()
  print(myvar)
end
end
a()
b()
setfenv(a,{myvar="me"})
b()
will print "hi" twice because b() only inherits the default fenv of a, if you change a's fenv then b gets disconnected from it





3 user(s) are reading this topic

0 members, 3 guests, 0 anonymous users