variable scope and listener parameters

Hi,

I’m new to Lua but am an experienced programmer.

I seem to be having trouble with variable scope, although the issue might be something else.

Some code snippets are as follows:

function chooseTeams()
chooseYourTeamHeading = display.newText(“Choose Your Team”, 0, 50, 0, 0, native.systemFontBold, 18)
chooseTeamType = “player”
chooseTeam()
end

function chooseTeam()
local bangladeshFlag = display.newImage(“flags_bangladesh.png”, 0, 90)
bangladeshFlag:addEventListener(“touch”, selectBangladeshTeam)
end
        
function selectBangladeshTeam()    
if chooseTeamType == “player” then playerTeam = “Bangladesh”
else computerTeam = teamName
end
finishSelectPlayerTeam()
end  

function finishSelectPlayerTeam()
chooseYourTeamHeading:removeSelf()
chooseYourTeamHeading = nil
end

So when the user clicks on the Bangladesh flag, finishSelectPlayerTeam() gets called, and the simulator comes up with this error

"Attempt to index global ‘chooseYourTeamHeading’ (a nil value).  I thought this was global because it wasn’t declared local, and therefore should be accessible?

On another matter, is it good practise to clean up all objects like this or is it not that important?

And finally, with the call to the event listener, do I need to setup a different function for each flag that I create?  Can I not have the one function that takes a parameter? eg

bangladeshFlag:addEventListener(“touch”, selectBangladeshTeam)

might become something like

bangladeshFlag:addEventListener(“touch”, selectTeam(“Bangladesh”))

thanks for your help!

Daniel

Hi Daniel, 

for the last question of yours… you will need to use closures to pass the parameter. 

i.e. 

bangladeshFlag:addEventListener(“touch”, function() selectTeam(“Bangladesh”) end )

So your selectTeam call is enclosed in an anonymous function and call the selectTeam with the correct parameter for each case.

As for the first problem… i will leave it for the more experienced lua programmers… since i’m learning myself as well… but usually i use a table and add methods to it, and then call self:method() when i want to call another method. When you call self:method() with the colon, you are invisibly passing self as the scope. 

i.e.

local myTable = {}

function myTable:chooseTeams()

end

function myTable:chooseTeam()

end

function myTable:selectBangladeshTeam()

    self:finishSelectPlayerTeam()

end

function myTable:finishSelectPlayerTeam()

    chooseYourTeamHeading:removeSelf()
    chooseYourTeamHeading = nil
end

But again… you should wait for the more experienced voice on this subject. I might be wrong.

Cheers 

Rodrigo

touch events trigger the function multiple times.  Once on press, a bunch if you move your finger while touching it, and finally one when you stop touching it.  When you press the button, it removes the display object.  When you stop touching the screen it tries to remove it a second time and that’s your error.

function selectBangladeshTeam(event)     if event.phase == "ended" then         if chooseTeamType == "player" then             playerTeam = "Bangladesh"         else             computerTeam = teamName         end         finishSelectPlayerTeam()     end     return true -- important end

You should localise the variable so scope hoisting works as expected.  This should solve your issues and is generally a good practice.

local chooseYourTeamHeading

function thatusesteamheading()

  – I can see it!

end

I’m going to guess that chooseTeams() isn’t called first which is why you get the nil variable.  As a general rule avoid global variables.  From what I understand your assumptions are correct.  But chooseTeams needs to be called first to make sure that the variable is set.

http://lua-users.org/wiki/ScopeTutorial is a great resource on scopes

Hi Daniel, 

for the last question of yours… you will need to use closures to pass the parameter. 

i.e. 

bangladeshFlag:addEventListener(“touch”, function() selectTeam(“Bangladesh”) end )

So your selectTeam call is enclosed in an anonymous function and call the selectTeam with the correct parameter for each case.

As for the first problem… i will leave it for the more experienced lua programmers… since i’m learning myself as well… but usually i use a table and add methods to it, and then call self:method() when i want to call another method. When you call self:method() with the colon, you are invisibly passing self as the scope. 

i.e.

local myTable = {}

function myTable:chooseTeams()

end

function myTable:chooseTeam()

end

function myTable:selectBangladeshTeam()

    self:finishSelectPlayerTeam()

end

function myTable:finishSelectPlayerTeam()

    chooseYourTeamHeading:removeSelf()
    chooseYourTeamHeading = nil
end

But again… you should wait for the more experienced voice on this subject. I might be wrong.

Cheers 

Rodrigo

touch events trigger the function multiple times.  Once on press, a bunch if you move your finger while touching it, and finally one when you stop touching it.  When you press the button, it removes the display object.  When you stop touching the screen it tries to remove it a second time and that’s your error.

function selectBangladeshTeam(event)     if event.phase == "ended" then         if chooseTeamType == "player" then             playerTeam = "Bangladesh"         else             computerTeam = teamName         end         finishSelectPlayerTeam()     end     return true -- important end

You should localise the variable so scope hoisting works as expected.  This should solve your issues and is generally a good practice.

local chooseYourTeamHeading

function thatusesteamheading()

  – I can see it!

end

I’m going to guess that chooseTeams() isn’t called first which is why you get the nil variable.  As a general rule avoid global variables.  From what I understand your assumptions are correct.  But chooseTeams needs to be called first to make sure that the variable is set.

http://lua-users.org/wiki/ScopeTutorial is a great resource on scopes