Problem with globals...

I have been trying to build a debug menu that is populated by variables that I’d like to modify on the fly, but I have been running into problems when I attempt to modify them from inside another module. Here is a stripped down example of the “main.lua”:

[lua]

first_global_value = 5

second_global_value = 10

print( "first_global_value: " … first_global_value … " and second_global_value: " … second_global_value )

local external_mod = require( “external_mod” )

external_mod.modifyValue()

print( "first_global_value: " … first_global_value … " and second_global_value: " … second_global_value ).

[/lua]

and the “external_mod.lua”:

[lua]

local M = {}

local table_values = { 

first_global_value,

second_global_value,

}

function M.modifyValue()

local i

for i = 1, #table_values do

table_values[i] = table_values[i] + 1

print( table_values[i] )

end

end

return M

[/lua]

The output is something like:

[lua]

first_global_value: 5 and second_global_value: 10

6

11

first_global_value: 5 and second_global_value: 10

[/lua]

I think when the variables are brought into the “table_values” table, the values are copied and not the references to the variables themselves. 

Any ideas on how to fix this problem? Thanks, Allen

You’re correct. The values of those variables are put into the table_values table, not a reference to the variables. That is how variables work. When you assign one variable to another you get a copy of the variable’s value.

What it looks like you want to do is have the names of the variables in a table and use that to modify the variables. The problem there is that there is no table to reference when updating the variables themselves. If you put the global variables into a table and make that global you could achieve that effect:

main.lua

global\_vars = { first=1, second=7 } print( global\_vars.first, global\_vars.second ) local ext\_mod = require("external\_mod") ext\_mod.modifyValues() print( global\_vars.first, global\_vars.second )

external_mod.lua

local m = {} function m.modifyValues() for key,value in pairs(global\_vars) do value = value + 1 global\_vars[key] = value print(key,value) end end return m

While I have not run this, what you should see is output like:

1, 7 2 8 2, 8

Thanks for the response. I was hoping I could reference the value directly, and not a copy of it in the table, due to the structure for the table I was planning on using. Here is a less stripped down version of main.lua

[lua]

first_global_value = 5

second_global_value = 10

print( "first_global_value: " … first_global_value … " and second_global_value: " … second_global_value )

local external_mod = require( “external_mod” )

external_mod.modifyValue()

print( "first_global_value: " … first_global_value … " and second_global_value: " … second_global_value )

[/lua]

and external_mod.lua

[lua]

local M = {}

local table_values = { 

{ variable = first_global_value, visible_name = “First Global Variable”, delta_value = 6 },

{ variable = second_global_value, visible_name = “Second Global Variable”, delta_value = 10 },

}

function M.modifyValue()

local i

for i = 1, #table_values do

table_values[i].variable = table_values[i].variable + table_values[i].delta_value

print( table_values[i].visible_name … ": " … table_values[i].variable )

end

end

return M

[/lua]

which outputs this:

[lua]

first_global_value: 5 and second_global_value: 10

First Global Variable: 11

Second Global Variable: 20

first_global_value: 5 and second_global_value: 10

[/lua]

Is this the wrong way to be thinking about the problem, or is there something I am missing?

Thanks again, Allen

This:

variable = first\_global\_value

copies the value of variable ‘first_global_value’ into the variable ‘variable’.

What you are trying to do is keep a pointer to the variable that you want to access, which is not possible in Lua. In C++ and many other languages it is, but not in Lua.

So, what you want to do is keep a table which contains named entries for all the values you want to access and then use that. That is why I created a table with named indices and you simply access the table using the names of the variables in the table.

Why do you have your mind so intently set on having a couple of variables free-roaming in your global code? Global variables are a bad thing. They lead to memory leaks, faulty logic, difficult to diagnose and resolve bugs and all sorts of gremlins. At the very least you should be keeping everything in a table and passing that table around as a reference, not trying to keep everything available in global variables. Also, global variables in Lua have a speed overhead because they are slower to access than local variables.

No, I totally understand about globals and minimize their usage. But I _will_ use that “globals” table to keep track of them better than I have been. Thanks!

The other part will be a little harder to deal with because I was hoping to use a table with data about the each of the variables (like a human readable name, the amount of the delta to add or subtract, etc) and will need to coordinate between the global table variables and the debug menu variables. But I think I’ll be able to figure something out.

Thanks, Allen

Put a table for each global variable within your actual global table - those individual tables can store as much data as you like about each value.

It looks more like you actually want something like a state bag - a table of values/tables - and this, too, should not be global. It should be passed around via parameters.

It is seriously bad practice to have data that you rely on being globally available. It leads to the things I mentioned before plus “tight coupling” which means you end up writing code which cannot be removed from that one piece of global code, making everything so much harder.

I would advise that you create a module which returns a table that has various useful values and functions which you can then use in each module of your application. This way, you don’t get locked into a piece of logic/data storage which is unchangeable and you can have functions which manipulate the data in that module, rather than having the code which changes those values spread out and copied throughout your application. Standard, reusable and easy to maintain. Then, if it grows to something more than just simple debugging globals, it’s manageable.

You’re correct. The values of those variables are put into the table_values table, not a reference to the variables. That is how variables work. When you assign one variable to another you get a copy of the variable’s value.

What it looks like you want to do is have the names of the variables in a table and use that to modify the variables. The problem there is that there is no table to reference when updating the variables themselves. If you put the global variables into a table and make that global you could achieve that effect:

main.lua

global\_vars = { first=1, second=7 } print( global\_vars.first, global\_vars.second ) local ext\_mod = require("external\_mod") ext\_mod.modifyValues() print( global\_vars.first, global\_vars.second )

external_mod.lua

local m = {} function m.modifyValues() for key,value in pairs(global\_vars) do value = value + 1 global\_vars[key] = value print(key,value) end end return m

While I have not run this, what you should see is output like:

1, 7 2 8 2, 8

Thanks for the response. I was hoping I could reference the value directly, and not a copy of it in the table, due to the structure for the table I was planning on using. Here is a less stripped down version of main.lua

[lua]

first_global_value = 5

second_global_value = 10

print( "first_global_value: " … first_global_value … " and second_global_value: " … second_global_value )

local external_mod = require( “external_mod” )

external_mod.modifyValue()

print( "first_global_value: " … first_global_value … " and second_global_value: " … second_global_value )

[/lua]

and external_mod.lua

[lua]

local M = {}

local table_values = { 

{ variable = first_global_value, visible_name = “First Global Variable”, delta_value = 6 },

{ variable = second_global_value, visible_name = “Second Global Variable”, delta_value = 10 },

}

function M.modifyValue()

local i

for i = 1, #table_values do

table_values[i].variable = table_values[i].variable + table_values[i].delta_value

print( table_values[i].visible_name … ": " … table_values[i].variable )

end

end

return M

[/lua]

which outputs this:

[lua]

first_global_value: 5 and second_global_value: 10

First Global Variable: 11

Second Global Variable: 20

first_global_value: 5 and second_global_value: 10

[/lua]

Is this the wrong way to be thinking about the problem, or is there something I am missing?

Thanks again, Allen

This:

variable = first\_global\_value

copies the value of variable ‘first_global_value’ into the variable ‘variable’.

What you are trying to do is keep a pointer to the variable that you want to access, which is not possible in Lua. In C++ and many other languages it is, but not in Lua.

So, what you want to do is keep a table which contains named entries for all the values you want to access and then use that. That is why I created a table with named indices and you simply access the table using the names of the variables in the table.

Why do you have your mind so intently set on having a couple of variables free-roaming in your global code? Global variables are a bad thing. They lead to memory leaks, faulty logic, difficult to diagnose and resolve bugs and all sorts of gremlins. At the very least you should be keeping everything in a table and passing that table around as a reference, not trying to keep everything available in global variables. Also, global variables in Lua have a speed overhead because they are slower to access than local variables.

No, I totally understand about globals and minimize their usage. But I _will_ use that “globals” table to keep track of them better than I have been. Thanks!

The other part will be a little harder to deal with because I was hoping to use a table with data about the each of the variables (like a human readable name, the amount of the delta to add or subtract, etc) and will need to coordinate between the global table variables and the debug menu variables. But I think I’ll be able to figure something out.

Thanks, Allen

Put a table for each global variable within your actual global table - those individual tables can store as much data as you like about each value.

It looks more like you actually want something like a state bag - a table of values/tables - and this, too, should not be global. It should be passed around via parameters.

It is seriously bad practice to have data that you rely on being globally available. It leads to the things I mentioned before plus “tight coupling” which means you end up writing code which cannot be removed from that one piece of global code, making everything so much harder.

I would advise that you create a module which returns a table that has various useful values and functions which you can then use in each module of your application. This way, you don’t get locked into a piece of logic/data storage which is unchangeable and you can have functions which manipulate the data in that module, rather than having the code which changes those values spread out and copied throughout your application. Standard, reusable and easy to maintain. Then, if it grows to something more than just simple debugging globals, it’s manageable.