Page 1 of 2

LUA question about visibility

Posted: Sat May 18, 2019 8:46 am
by Lbenet
Hello,

Well, I didn't see a presentation forum, so "Hello" to everybody.

I am new to Lua, so I have been reading the manual reference but I don't get some concepts. I come from C++ and SFML, with the feeling by now it is a more rigid language (although I have never dominated it). Seeing how Love2D is like, I think it will be better for my goals.

Don't hesitate to show me another Lua books, reference guides or forums if the question doesn't fit here, and fit better there. Ah! Also I am not native english speaker, so I am sorry about my english.

So, my question... I am building an application to write chemistry equations by clicking on a periodic table. The question is about visibility. I have the next code:

Code: Select all

local periodic_table

function love.load()
	periodic_table = require 'periodic_table'
	love.window.setMode(1500, 900)
	periodic_table:load()
end
There, in periodic_table I have the next code:

Code: Select all

periodic_table = {}

function periodic_table:load()
	local element = require("element")
	-- lots of code more
end
And the question is that in main I can do the next:

Code: Select all

function love.draw()
	periodic_table:draw()
	element.WIDTH = 5
end
Why I can change "element.WIDTH", if it was a local object of "periodic table" inside the "load" function? I think I could not access to element because it is not in the scope, but I can do it and it has effect on the "element" object. "WIDTH" is an existent key of "element".
Really I am not interested in change "element" but I want to learn what is happening. In C++ I worked with several books wich defined the language in great detail, but I have other feelings with Lua.

Re: LUA question about visibility

Posted: Sat May 18, 2019 1:38 pm
by grump
Lbenet wrote: Sat May 18, 2019 8:46 am And the question is that in main I can do the next:

Code: Select all

function love.draw()
	periodic_table:draw()
	element.WIDTH = 5
end
Why I can change "element.WIDTH", if it was a local object of "periodic table" inside the "load" function? I think I could not access to element because it is not in the scope, but I can do it and it has effect on the "element" object. "WIDTH" is an existent key of "element".
The only explanation for this behavior is that the actual code is different from the code you have shown. The table named element does not exist outside periodic_table:load with this code, and can't be altered from outside the function. Check if you have a global variable with the same name defined somewhere.

Re: LUA question about visibility

Posted: Sat May 18, 2019 2:08 pm
by pgimeno
grump is right. It's just guesswork, but one likely explanation is that 'element' is defined as a global inside element.lua, just like periodic_table is defined as a global in the snippet you have shown of periodic_table.lua. Change it to this if you don't want it global:

Code: Select all

local periodic_table = {}
...
Similarly, in element lua, if you have this, which is what I suspect:

Code: Select all

element = {}
...
then just change it to this:

Code: Select all

local element = {}
...
That way, they will be local to the file they are defined in, rather than global.

Re: LUA question about visibility

Posted: Sat May 18, 2019 8:05 pm
by KayleMaster
I'm not sure if code is missing, or you just didn't quite grasp Lua.

Code: Select all

periodic_table = {}

function periodic_table:load()
	local element = require("element")
	-- lots of code more
end
You're requiring this module from love.load with

Code: Select all

periodic_table = require 'periodic_table'
But because you don't have local in front of "periodic_table = {}" that is now a global variable.
The proper way to do this is:

Code: Select all

local periodic_table = {}

function periodic_table:load()
	local element = require("element")
	-- lots of code more
end

return periodic_table
Next, you're defining an element in the load function, I assume element will have the same structure (local element = {} - do stuff with element - return element), however, that element is only visible to the function.
Your code is pretty wrong with the access of "element.WIDTH". You don't have traces of element in your main.lua.

What you want to do is this:

Code: Select all

local periodic_table = {}

function periodic_table:load()
	self.element = require("element")
	-- lots of code more
end

return periodic_table
Now you access the element using:

Code: Select all

function love.draw()
	periodic_table:draw()
	periodic_table.element.WIDTH = 5
end
Why you can access the element? Probably because of the same mistake you did with defining your periodic table - you missed local in front of it and it became a global variable.

However you need to look up how require works. It only runs the file it requires the first time. Every second time it just returns what it returned the first time. If you have multiple elements, I'd advise you to look at PIL's tutorial for classes/objects or use something like middleclass.

Re: LUA question about visibility

Posted: Sun May 19, 2019 7:11 am
by Lbenet
Thank you for all responses!

I said that I came from C++, but it is true that I only have made simple things and I have some problems to grasp the OOP concepts or at least how to organise it, but I had good documentation about the language (there are tons of books) so I advanced step-by-step. But Lua seems to be faster to code, so I choosed it.

So the point is that I wrote this code:

Code: Select all

function tabla:load()

	local elemento = require 'elemento'

	table.insert(self, elemento:new("H", "Hidrogeno", 1.008, 1, 2.1, 2, 2, "BLANCO"))
	table.insert(self, elemento:new("Li", "Litio", 6.941, 3, 1.0, 3, 2, "BLANCO"))
	table.insert(self, elemento:new("Na", "Sodio", 22.990, 11, 0.9, 4, 2, "BLANCO"))

end
But I didn't declare element as local in its file: I though it was enough declaring it as a local one time when I "require" the file in the function (I though "local" was applied to the complete file). So, in the file I had:

Code: Select all

elemento = {}
-- more code
Changing to:

Code: Select all

local elemento = {}
-- more code
All works as expected, I can not access to "elemento".
Thank you!

Re: LUA question about visibility

Posted: Sun May 19, 2019 8:42 am
by raidho36
The "require" function simply loads the file into memory (and runs it). If the file returned something at the end, then this is returned from the "require" function. The file in question is loaded exactly once, and then the same value is returned from "require" it every time you call it. You can use it the way you use it, but the way it works is more clearly telegraphed when you code it as following:

Code: Select all

local class = require ( "class" )

local instance1 = class ( "foo" )
local instance2 = class ( "bar" )

Re: LUA question about visibility

Posted: Sun May 19, 2019 9:34 am
by grump
raidho36 wrote: Sun May 19, 2019 8:42 am

Code: Select all

local class = require ( "class" )

local instance1 = class ( "foo" )
local instance2 = class ( "bar" )
Either your terminology is off, or I don't understand what this is supposed to do. Why does the class function return instances?

Re: LUA question about visibility

Posted: Sun May 19, 2019 10:39 am
by raidho36
It's a common practice to call the class to create new instances of the class, provided "__call" metamethod is defined. It's equivalent of calling class:new but uses Lua builtin dispatch system instead of actually calling "new" manually.

Re: LUA question about visibility

Posted: Sun May 19, 2019 11:23 am
by pgimeno
Lbenet wrote: Sun May 19, 2019 7:11 am But I didn't declare element as local in its file: I though it was enough declaring it as a local one time when I "require" the file in the function (I though "local" was applied to the complete file).
'require' does not work like 'include' in C/C++: it does not preserve the scope of the current block; instead it creates a new top-level scope, therefore everything you declare within the file which isn't local will be global.

Similarly, there's a limit of 200 active locals per file, but the count resets for files you require().

I am saying 'file' above, but I really mean 'chunk', which is the term that the Lua manual uses (a chunk is a more general concept, as it can come from a string, for example). And the same applies to 'require', 'dofile', 'load', 'loadfile' and 'loadstring'.

(Edited to place the correct maximum of active locals, thanks guys)

Re: LUA question about visibility

Posted: Sun May 19, 2019 1:56 pm
by raidho36
pgimeno wrote: Sun May 19, 2019 11:23 am there's a limit of 256 active locals per file, but the count resets for files you require().
Last I heard the limit was exactly 200 for any given scope.