on Globals to Locals and back again...

So the blog on hunting globals here… 
 

https://coronalabs.com/blog/2016/04/16/check-those-pesky-globals/

I asked a question, basically this…

 

Can you turn a global local by just declaring it local? Reason I ask,

I set up something like:
local drawOrder = {spriteToDisplay2, spriteToDisplay4, spriteToDisplay1, spriteToDisplay3}

it hits that and pounds my console with ‘reading global nils’

Then a little bit later I do:
local spriteToDisplay1=display.newSprite( sheet, sequenceData)
local spriteToDisplay2=display.newSprite( sheet, sequenceData)
etc…

and I don’t get any global warnings. I then made a simple test=3 then local test=5, print (test). and got 1 error, where if I don’t put local for test then I get 3 global set warning. So I guess I answered my own question? just want to make sure.

Rob Miracles answer was

Lua is a one pass compiler system. When it is parsing your code and sees spriteToDisplay2 as a variable that has not been previously declared local, it assumes you want a global variable and it gets assigned a memory address.

Later, when you do local spriteToDisplay2… You have created a local version (it has it’s own memory address) and you can use it as a local. However, drawOrder still has the addresses for the global. If your local spriteToDisplay were to go out of scope, it would fall back to the last definition.

It’s best illustrated here:

local number = 10
if true then
local number = 20
end
print (number) — prints 10

While I did that with all locals, the concept is the same. Globals are the highest order in scoping. If you use the same name later as a local, it’s a new variable. If you use the same local inside another block and give it a local, its a new variable. As the scope stack pops back up, the version that is in scope at that time becomes active.

Which I think makes sense. As soon as a Corona sees a Var, if it is not defined local, it will allocate it to Global. And if you define it local, it is creating a new address(?) And now there are two. right? So would it be best for me to define the spriteToDisplays as local before the drawOrder references them in its own declaration.

right?

Yes, declare them local before you need to use them.

local spriteToDisplay1, spriteToDisiplay2, spriteToDisplay3, spriteToDisplay4 local drawOrder = {spriteToDisplay2, spriteToDisplay4, spriteToDisplay1, spriteToDisplay3} spriteToDisplay1=display.newSprite( sheet, sequenceData) spriteToDisplay2=display.newSprite( sheet, sequenceData)

The first local line will give each variable and address, drawOrder will be populated correctly and then you can actually make the objects later when you need them.

Rob

@Lava Level 

Remember, locals are scope sensitive.  

Just having a local in some specific scope does not block the creation of a global with the same name later in some other scope.

The key thing to remember is, if you assign a value to a variable and that variable is not already defined as local you WILL create a global.  

In short you need to be careful about the use (or non-use) of the keyword local.  Pre-declare variables before you use them.  

Note: There is one exception:

local function doit( bob, sue ) -- bob and sue are automatically local and exist only in the scope of this function end

roaminggamer, well if it is at the top scope of my module or top scope of a Composer Module, then it should see it throughout the module as if it was global. At least that is what I have noticed.  Then I can use it in other functions as if it was global. (is module the correct term? I think you might get what I mean)

Also, somewhere (the irc channel?) I heard that each module can only have a limited amount of local variables declared. Not sure where I heard that or what the number is. But it caused me to do pack my variables more.

For instance, I use to just have locals defined at the top. And I had a LOT of them. like my tables I use for reference throughout my code

local nameTable = { "a name", "another name", "Yet another name"} local colorTable = { "green", "blue", "red", "orange"} local spriteToUse = {} local brightness= {} local brightness.red = 0 local brightness.green =0 local brightness.blue = 0

So much like the brightness, I just started stacking them into one variable.

local tbl = {}  -- for table

then
 

tbl.nameTable = { "a name", "another name", "Yet another name"} tbl.colorTable = { "green", "blue", "red", "orange"} tbl.spriteToUse = {}

…etc…

I do the same for integers so I can have some basic numbers to mess with in for loops. 
 

local int = {} int.num1 = 0 int.num2 = 0 ​int.num3 = 0

so since they are all dependent on int or tbl, They are forced to already be declared local I believe? Plus I can wipe them easier.
That way I have a lot less variable declarations. Is this a good thing to do as well? And what are the limits on locals for a Composer module?
 

I even do this with my game functions so I can jump around in the code. like…

local MainFunctions = {} function MainFunctions.DungeonMasterProcessor() -- stuff end function MainFunctions.moveMonster() --stuff end MainFunctions.playerHasDied = function () --stuff end MainFunctions.onHealthMeter = function (Damage) --stuff end

This is why I hate doing code in blog comments :slight_smile:

Over there I talked about this:

number = 5 local number = 10 if true then     local number = 20 end print (number) — prints 10

In this example, a global, “number” is created with the value of 5. But then a new local variable is create with the value of 10. Inside the if, a local to the inside of the if is created and set to 20. At the end, the number with the value of 20 goes out of scope and the local number = 10 comes back into scope.

What I didn’t say before was that if you changes scenes and print the value of number you will get 5 because that’s the global version of number.

As far as using tables for things. I love this technique. My first game had a ton of local variables to the point I was hitting the 200 limit (and still do). So I started using tables to  hold things.

In my more modern code I use a data module:

local M  = {}

return M

and call it myGlobals or myData (My choice for the name) and I shove anything I need to be around in multiple scenes in myData and this can include functions too. Perhaps this would be better with more semantically correct names.

But its a good technique none the less.

Rob

Ah… Yeah, my game is data HEAVY because it’s an RPG. So my game, I have it set up like this with scenes.

scene_Intro

scene_MainMenu

scene_MakePlayer

All of that sets up the Json files for what character you created and what is being used at the moment. Then I go to:

scene_game 
scene_inventory
scene_maps

scene_youDied

all of my ‘levels’ (level data) get loaded into scene_game which then loads Mod_Layout which loads the graphics for what is in that particular level. (ie. I dont load ALL the enemies and terrain, just what is referenced in the JSON)

If you are in scene_game and go to another ‘level’ then I save current level, and save the new level to load in JSON, I call scene_Nuke which wipes everything. wipes scene_game completely then reloads it. This seems to work great. I monitor my mem and texMem to make sure to goes back down to something reasonable.

So scene_game becomes more of a state Machine that handles everything more or less.

If a scene doesn’t have something (for instance inventory has no idea what you are doing) I use something like this… 
 

composer.setVariable( "transferVar1", playerData ) composer.setVariable( "transferVar2", gpMode)

That way playerData (which holds all your inventory items, health pts, etc.) is sent to the scene_Inventory
same for gpMode (gameplay mode, so I have an idea whats going on in scene_game from the inventory)

remember I am ‘turn based’ so I can get away with some things a realtime game couldn’t i guess.
 

(oh jeesh it’s embarrassing explaining this since I could be doing it totally wrong, but it works, just want to keep it streamlined, global hunted, and memory managed. Hence all these questions.)

also did you see what I said about my functions? is that Kosher?

 

Yes, declare them local before you need to use them.

local spriteToDisplay1, spriteToDisiplay2, spriteToDisplay3, spriteToDisplay4 local drawOrder = {spriteToDisplay2, spriteToDisplay4, spriteToDisplay1, spriteToDisplay3} spriteToDisplay1=display.newSprite( sheet, sequenceData) spriteToDisplay2=display.newSprite( sheet, sequenceData)

The first local line will give each variable and address, drawOrder will be populated correctly and then you can actually make the objects later when you need them.

Rob

@Lava Level 

Remember, locals are scope sensitive.  

Just having a local in some specific scope does not block the creation of a global with the same name later in some other scope.

The key thing to remember is, if you assign a value to a variable and that variable is not already defined as local you WILL create a global.  

In short you need to be careful about the use (or non-use) of the keyword local.  Pre-declare variables before you use them.  

Note: There is one exception:

local function doit( bob, sue ) -- bob and sue are automatically local and exist only in the scope of this function end

roaminggamer, well if it is at the top scope of my module or top scope of a Composer Module, then it should see it throughout the module as if it was global. At least that is what I have noticed.  Then I can use it in other functions as if it was global. (is module the correct term? I think you might get what I mean)

Also, somewhere (the irc channel?) I heard that each module can only have a limited amount of local variables declared. Not sure where I heard that or what the number is. But it caused me to do pack my variables more.

For instance, I use to just have locals defined at the top. And I had a LOT of them. like my tables I use for reference throughout my code

local nameTable = { "a name", "another name", "Yet another name"} local colorTable = { "green", "blue", "red", "orange"} local spriteToUse = {} local brightness= {} local brightness.red = 0 local brightness.green =0 local brightness.blue = 0

So much like the brightness, I just started stacking them into one variable.

local tbl = {}  -- for table

then
 

tbl.nameTable = { "a name", "another name", "Yet another name"} tbl.colorTable = { "green", "blue", "red", "orange"} tbl.spriteToUse = {}

…etc…

I do the same for integers so I can have some basic numbers to mess with in for loops. 
 

local int = {} int.num1 = 0 int.num2 = 0 ​int.num3 = 0

so since they are all dependent on int or tbl, They are forced to already be declared local I believe? Plus I can wipe them easier.
That way I have a lot less variable declarations. Is this a good thing to do as well? And what are the limits on locals for a Composer module?
 

I even do this with my game functions so I can jump around in the code. like…

local MainFunctions = {} function MainFunctions.DungeonMasterProcessor() -- stuff end function MainFunctions.moveMonster() --stuff end MainFunctions.playerHasDied = function () --stuff end MainFunctions.onHealthMeter = function (Damage) --stuff end

This is why I hate doing code in blog comments :slight_smile:

Over there I talked about this:

number = 5 local number = 10 if true then     local number = 20 end print (number) — prints 10

In this example, a global, “number” is created with the value of 5. But then a new local variable is create with the value of 10. Inside the if, a local to the inside of the if is created and set to 20. At the end, the number with the value of 20 goes out of scope and the local number = 10 comes back into scope.

What I didn’t say before was that if you changes scenes and print the value of number you will get 5 because that’s the global version of number.

As far as using tables for things. I love this technique. My first game had a ton of local variables to the point I was hitting the 200 limit (and still do). So I started using tables to  hold things.

In my more modern code I use a data module:

local M  = {}

return M

and call it myGlobals or myData (My choice for the name) and I shove anything I need to be around in multiple scenes in myData and this can include functions too. Perhaps this would be better with more semantically correct names.

But its a good technique none the less.

Rob

Ah… Yeah, my game is data HEAVY because it’s an RPG. So my game, I have it set up like this with scenes.

scene_Intro

scene_MainMenu

scene_MakePlayer

All of that sets up the Json files for what character you created and what is being used at the moment. Then I go to:

scene_game 
scene_inventory
scene_maps

scene_youDied

all of my ‘levels’ (level data) get loaded into scene_game which then loads Mod_Layout which loads the graphics for what is in that particular level. (ie. I dont load ALL the enemies and terrain, just what is referenced in the JSON)

If you are in scene_game and go to another ‘level’ then I save current level, and save the new level to load in JSON, I call scene_Nuke which wipes everything. wipes scene_game completely then reloads it. This seems to work great. I monitor my mem and texMem to make sure to goes back down to something reasonable.

So scene_game becomes more of a state Machine that handles everything more or less.

If a scene doesn’t have something (for instance inventory has no idea what you are doing) I use something like this… 
 

composer.setVariable( "transferVar1", playerData ) composer.setVariable( "transferVar2", gpMode)

That way playerData (which holds all your inventory items, health pts, etc.) is sent to the scene_Inventory
same for gpMode (gameplay mode, so I have an idea whats going on in scene_game from the inventory)

remember I am ‘turn based’ so I can get away with some things a realtime game couldn’t i guess.
 

(oh jeesh it’s embarrassing explaining this since I could be doing it totally wrong, but it works, just want to keep it streamlined, global hunted, and memory managed. Hence all these questions.)

also did you see what I said about my functions? is that Kosher?