Behaviour of "local"

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Behaviour of "local"

Terence Martin-2
I figured it's been long enough around here without me saying something
stupid, so...

I'm fooling around with a sort of module system (using some code posted to
the list by Roberto) and I noticed that if you define a variable outside of
a function as local, then any global function that references it is
implicitly local as well. This makes sense, but I was more expecting
something like an error message or for the function to try and access a
global. I checked the manual but I didn't notice this mentioned anywhere. I
thought I'd mention it in case I'm right and it's not mentioned in the
manual, so that it could perhaps be added to a future version. Of course,
it's probably there and I just missed it...



Reply | Threaded
Open this post in threaded view
|

Re: Behaviour of "local"

Luiz Henrique de Figueiredo
>I noticed that if you define a variable outside of
>a function as local, then any global function that references it is
>implicitly local as well. This makes sense, but I was more expecting
>something like an error message or for the function to try and access a
>global.

You do get an error message. See below. Perhaps you could post a small sample
of what you mean.

$ cat i
local x

function f()
 print(x)
end

$ lua -v i
Lua 4.0  Copyright (C) 1994-2000 TeCGraf, PUC-Rio
error: cannot access a variable in outer scope;
  last token read: `x' at line 4 in file `i'


--lhf

Reply | Threaded
Open this post in threaded view
|

Re: Behaviour of "local"

Terence Martin-2
> You do get an error message. See below. Perhaps you could post a small
sample
> of what you mean.

test.lua
-------
function import (filename)
 local newenv = {}
 local oldenv = globals ()
 local oldtm = gettagmethod (tag (nil) , 'getglobal')
 settagmethod (tag (nil) , 'getglobal' , function (varname)
  return %oldenv[varname]
 end)
 globals (newenv)
 dofile (filename)
 globals (oldenv)
 settagmethod (tag (nil) , 'getglobal' , oldtm)
 return newenv
end

module = import ("module.lua")

foreach (module , print)

module.lua
-----------
local modname = "mod1"

function report ()
 print ("report in the module")
 print (modname)
end

When you run test.lua with module written this way, the function report
isn't printed. I presume this is because it's not stored in the globals
table. If, however, you make modname be a global, or change the line in
report () to read "print (%modname)" then report becomes a global.

Perhaps I'm just doing something wacky?


Reply | Threaded
Open this post in threaded view
|

Re: Behaviour of "local"

Luiz Henrique de Figueiredo
In reply to this post by Terence Martin-2
>When you run test.lua with module written this way, the function report
>isn't printed.

The problem is that module.lua gives a parse error:

$ lua module.lua
error: cannot access a variable in outer scope;
  last token read: `modname' at line 7 in file `module.lua'

However, "import" loads module.lua using an empty environment, one that does
not even contain _ERRORMESSAGE, and so no message is reported.
Try
	local newenv = {_ERRORMESSAGE=_ERRORMESSAGE}

The code you used for "import" was based on some code posted to the list
as an example. For production, you have to be careful when you use "globals",
because almost everything "vanishes".
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: Behaviour of "local"

Terence Martin-2
> However, "import" loads module.lua using an empty environment, one that
does
> not even contain _ERRORMESSAGE, and so no message is reported.
> Try
> local newenv = {_ERRORMESSAGE=_ERRORMESSAGE}
>
> The code you used for "import" was based on some code posted to the list
> as an example. For production, you have to be careful when you use
"globals",
> because almost everything "vanishes".
> --lhf

Yes this is far from "production". I only started experimenting with
Roberto's code as a starting point last night and then I noticed this. Your
explanation makes sense, but leaves me confused about why the getglobal tag
method that import sets lets the code executed with dofile see global
functions like print and globals from the file that called import, but not
_ERRORMESSAGE.


Reply | Threaded
Open this post in threaded view
|

Re: Behaviour of "local"

Luiz Henrique de Figueiredo
In reply to this post by Terence Martin-2
>but leaves me confused about why the getglobal tag
>method that import sets lets the code executed with dofile see global
>functions like print and globals from the file that called import, but not
>_ERRORMESSAGE.

Because _ERRORMESSAGE is called implicitly in ldo.c and its value is not
obtained by calling lua_getglobal (calling lua_getglobal when handling errors
might generate other errors...)
But, yes, I see your point.
--lhf