odd scope bug?

I’m having a variable scope issue. not sure if this is something i’m doing wrong but through reading all the docs it seems that this should work.

I have a global variable

totalCash=100000

Inside a function in a sub file, i have a line

totalCash = totalCash-52000

at the end of this method I do a native.showAlert and can see the value is correctly set at 48000 (so it saw the global variable, and should be setting the global value). The immediate next line is

nextScreen=require(“travel”);
nextScreen.run();

the first line of run() in the travel file is
native.showAlert(totalCash,totalCash);
which shows 100000. Why would it see the first value and not the newly updated value?? [import]uid: 6317 topic_id: 1002 reply_id: 301002[/import]

You’re almost going to have to give us example code that fails because much depends on your implementation.

I would suggest that using a global in this way, while it might seem convenient, it allows for significant bug issues since this value can be changed anywhere and not “checked”.

Do you have “module(…, package.seeall)” at the top of your “subfiles”?

Scott [import]uid: 5659 topic_id: 1002 reply_id: 2431[/import]

yes i have that on the top of all the subfiles. Here are all my files.

main.lua

display.setStatusBar (display.HiddenStatusBar)
totalCash = 100000;

local shipYard = require(“shipyard”);
shipYard.run();

shipyard.lua

module(…, package.seeall)

local function shipPurchased(purchasedShip)

totalCash = totalCash - 52000;

timer.performWithDelay(200, function()
local travel = require(“travel”);
travel.run();
end)
end

function shipClicked()
buyLabel = display.newImage(“5a_buyshipbutton.png”);
buyLabel.xScale=.5; buyLabel.yScale=.5;
buyLabel.x=50; buyLabel.y=350-60;
buyLabel:addEventListener(“touch”, function()
shipPurchased()
end );
end

function run()

shipSmall1 = display.newImage(“5a_buyshipbutton.png”);
shipSmall1.xScale=.3; shipSmall1.yScale=.3;
shipSmall1.x=display.stageWidth/5*4+30; shipSmall1.y=-75;
shipSmall1.shipId=1;

transition.to(shipSmall1, {delay=3400, time=500, y=45})

shipSmall1:addEventListener(“touch”,
function()
shipClicked();
end)

end

travel.lua

module(…, package.seeall)

function run()
native.showAlert(totalCash, totalCash);
end
[import]uid: 6317 topic_id: 1002 reply_id: 2441[/import]

I’ll take a quick look tomorrow. Something that they just recently got working in the forums is the code tag.

Surround your code parts with <code> and </code>. Makes it a lot easier to read.

Scott [import]uid: 5659 topic_id: 1002 reply_id: 2443[/import]

Or < lua > < /lua > :slight_smile: [import]uid: 5712 topic_id: 1002 reply_id: 2451[/import]

anyone have any comments on this thread? I’m still experiencing and its causing alot of issues in my app given my design of different files instead of using one big main.lua. its a pretty large app… thanks! [import]uid: 6317 topic_id: 1002 reply_id: 2654[/import]

use _G[“totalCash”] = _G[“totalCash”] - 52000

that will access the global variable, your code also loops 4 times so you get this outputted in terminal

48000
-4000
-56000
-108000

what you can do is define a lua require that controls and handles CASH, define the variable storing CASH in there and write functions to manipulate the CASH
so cash.lua would look like

– Setup
totalCash = 100000

– Return Cash
function returnCash()
return totalCash
end

– Add Cash
function addCash( cash )
totalCash = totalCash + cash
end

– Subtract Cash
function subtractCash( cash )
totalCash = totalCash - cash
end
and keep going like that and require in main.lua, then in main or any other required file you can just use cash.addCash( 56000 )

What you will find in this method is that if you write the app correctly you will have an easy time, each lua file only manipulating what it needs to on a local level and the optional returnCash to pass the real cash value to other required files. Look at sprite.lua or ui.lua these files are not written in any special way, they are written to save time and present functionality in a specific way and as such it keeps your code cleaner, its easy to debug and when your app grows it will still be easy to navigate, cash not adding up correctly, check cash.addCash() etc…

I dont even have the app runtime in main.lua (main.lua calls it) I have one called runtime.lua as that was starting to get big.

Even more so load your graphics in the require files, write a function in each called loadAssets(), this will allow you to control when things are loaded but also on boot it will allow you to animate a loading graphic as you can load assets after main.lua has run once and the app is setup and going.

Needs anything else just ask
[import]uid: 5354 topic_id: 1002 reply_id: 2685[/import]

awesome thanks for the tips! [import]uid: 6317 topic_id: 1002 reply_id: 2691[/import]

Matthew is right about rewriting your code and breaking it up into separate class files. Much easier to deal with.

You’ll also notice one of the things he’s doing in his suggestion is passing the variable as an argument to the class methods, e.g. cash.addCash( 56000 ). By passing the variable totalCash to travel.run, you should be able to get your code working without a lot of changes.

Also, I’m not sure if you noticed, but try running your code with Corona Terminal and make sure you’re seeing the output. You’ll notice that shipPurchased is running 4 times and trying to call the native alert 4 times. It’s also subtracting from your totalCash value 4 times. Use the “ended” phase event that’s sent from the touch listener to make sure your function only runs once. “ended” is kind of like button “release”.

I’ve modified your code by adding the phase event “ended” and by adding totalCash as an argument to travel.run. Take a look:

main.lua
—8[code]
display.setStatusBar (display.HiddenStatusBar)
totalCash = 100000;

local shipYard = require(“shipyard”);
shipYard.run();
[/code]

shipYard.lua
—8[code]
module(…, package.seeall)

function shipPurchased(event)
local phase = event.phase

if “ended” == phase then
totalCash = totalCash - 52000;
print(totalCash)
timer.performWithDelay(200, function()
local travel = require(“travel”);
travel.run(totalCash);
end)
end
end

function shipClicked(event)
local phase = event.phase

if “ended” == phase then
buyLabel = display.newImage(“5a_buyshipbutton.png”);
buyLabel.xScale=.5; buyLabel.yScale=.5;
buyLabel.x=50; buyLabel.y=350-60;
buyLabel:addEventListener(“touch”, shipPurchased);
end
end

function run()
shipSmall1 = display.newImage(“5a_buyshipbutton.png”);
shipSmall1.xScale=.3; shipSmall1.yScale=.3;
shipSmall1.x=display.stageWidth/5*4+30; shipSmall1.y=-75;
shipSmall1.shipId=1;

transition.to(shipSmall1, {delay=3400, time=500, y=45})

shipSmall1:addEventListener(“touch”, shipClicked)
end
[/code]

travel.lua
—8[code]
module(…, package.seeall)

function run(totalCash)
native.showAlert(totalCash, totalCash);
end
[/code]

Best,
Gilbert [import]uid: 5917 topic_id: 1002 reply_id: 2715[/import]

Gilbert,

I’m new to Lua and was able to follow your modified code but to me it doesn’t answer the “scope” question. totalCash was first defined in main.lua and accessed in shipYard.lua, in the same manner as the original code. The only difference seems to be that totalCash was passed as a argument to travel.lua instead of having travel.lua access it as a global variable.

So the question is why can shipYard.lua see the global variable correctly but travel.lua can’t? Without passing totalCash as an argument it looks like it accesses the totalCash variable defined in main.lua and the one modified in shipYard.lua (in shipPurchased function) is local to that module. What am I missing?

Thanks,
Tom [import]uid: 6119 topic_id: 1002 reply_id: 2723[/import]

A required class cant see outside its own scope, this got me a bit confused up when I first started a couple of months ago. I suppose its because there shouldnt be a need for a class to do that, it would kill portability.

As a special case _G[“totalCash”] accesses the global variable but its slower to access memory out side of the scope like this, if you do it a lot in a loop in between frames it can take its toll.

You can assign properties to objects, classes etc… as well so if I have an alien spite I can attach properties to it

local alien = sprite.newAnim{ “image1.png” , “image2.png” }
– variables ive assigned
alien.life = 9
alien.speed = 5
alien.found = 0
– properties i can alter
alien.alpha = 0
alien.isVisible = false
alien.x= 50
alien.y = 200

[import]uid: 5354 topic_id: 1002 reply_id: 2724[/import]

It seems that shipYard.lua and travel.lua can see the totalCash variable defined in main.lua (which seems out of their scope). When shipYard.lua modifies the value of totalCash it then becomes local to that class? Based on your statement I would assume totalCash to be local to the class with a initial nil value but it takes on the value set in main.lua.

Tom [import]uid: 6119 topic_id: 1002 reply_id: 2725[/import]

I think it sees the value as it is set at compile time rather than the current in memory version [import]uid: 5354 topic_id: 1002 reply_id: 2726[/import]

It seems odd (or a bug) that modules can see the initial value of a global variable defined in main.lua but not see the modified value.

Thanks for your explanation and I’ll keep it in mind as I move forward in my Lua understanding.

Tom [import]uid: 6119 topic_id: 1002 reply_id: 2755[/import]

Ok… to me it seams stuff is still not explained enough!

Esp. because “Module” and “Class” get mixed up… one thing does not imply the other thing…
If you specify

module(..., package.seeall)  

in your Module you will get a state which looks like you have a “copy” of the global variables of the calling module at the time the module is loaded and they become their own locals to this module!

If you do not specify this… you will get directly to those global variables (but it is not a module then)!

This is my conclusion and is illustrated by this test code which is quiet “surprisingly” at first…

-- main.lua  
  
test='A' -- not local test!!  
  
print("main1: "..test)  
  
require 'mod.lua'  
  
print("main2: "..test)  
  
-- mod.lua  
  
print("mod1: "..test)  
  
test='B'  
  
print("mod2: "..test)  
  
module(..., package.seeall)  
  
print("mod3: "..test)  
  
test='C'  
  
print("mod4: "..test)  
  

This code will print:

main1: A  
mod1: A  
mod2: B  
mod3: B  
mod4: C  
main2: B  

You may modify it for testing different things…

For example try “module(…)” … instead of “module(…, package.seeall)”

But best you read “PIL 2nd” page 137 ff… for those topics… [import]uid: 6928 topic_id: 1002 reply_id: 3300[/import]

I found this thread super helpful - as I had run into the same early-lua-learner’s confusion about scope in ‘require’ modules.

Documentation in the main Corona SDK programming orientation docs should underline this. There are places there that simply state variables are either local or global… which, some of us learned through some comfusing debugging, isn’t true when it comes to modules connected through ‘require’

Bottom line things I’d underline would be (as said in the preceding posts)

  • ‘require’ included files can’t see ‘globals’ you think you’ve declared in main.
  • it’s much better to forget about globals anyway - and create explicit functional control and parameter passing to manage anything important enough to be knowable across functions.

I finally ‘got it’ – but I can’t believe I had to go through the confusion and then, thankfully, find this thread to get it sorted out.

Thanks again to everyone who laid things out above.
[import]uid: 34130 topic_id: 1002 reply_id: 27537[/import]