LUA modules + local variables

Hi guys,

I have problem with Lua modules.
Let’s say there is a module Data.lua:

local M = {};
M.grid = {};
return M;

Also there are two scripts Player.script and GameController.script.
They both require the module like this:

local data = require "modules.Data"

The problem is that both scripts see different data.grid variable. It looks like every time a script requires a module it gets an instance of that module.
I also tried to print(data.grid) in order to get its address:
Player.script: table: 0x0bfe7800
GameController.script: table: 0x0a3de490

I expected that described module to behave as a singleton.
What I am doing wrong?

1 Like

I can tell more.
If there is another module OtherData.lua:

local M = {};
M.list = {};
return M;

And Data.lua requires OtherData.lua like this:

local otherData = require "modules.OtherData"

And Data.lua provides access to list variable like this:

function M.getList()
 return otherData.list;
end

Then list variable is the same for both scripts (Player.script and GameController.script).

And one more thing.
Player.script is attached to dynamically created game object.

Edit: removing my earlier comment to not spread misinformation! Sorry for the confusion! :slight_smile:

I understand if it comes to a scripts. But it is about modules. Shouldn’t they behave like singletons?

It is expected for Lua modules to be the same, because of a caching mechanism in lua. Text-search for “cache” here: http://lua-users.org/wiki/ModulesTutorial

I tried to recreate your case, and curiously I don’t see the same result. For me each require’d module is the same, as expected.

This is my test:

mod.lua:

local M = {}
M.test_val = 1

M.alter = function ()
	M.test_val = M.test_val + 1
end

M.read = function ()
	return M.test_val
end

return M

a.script:

local mod = require("test.mod")

function init(self)
	print("a")
	print(mod)
	mod.alter()
	print(mod.read())
end

b.script:

local mod = require("test.mod")

function init(self)
	print("b")
	print(mod)
	mod.alter()
	print(mod.read())
end

Output:

DEBUG:SCRIPT: a
DEBUG:SCRIPT: table: 0x0e4013d0
DEBUG:SCRIPT: 2
DEBUG:SCRIPT: b
DEBUG:SCRIPT: table: 0x0e4013d0
DEBUG:SCRIPT: 3

However, if you would uncheck script > shared_state in game.project, and require from different script types (e.g. one .script and one .gui_script), the modules would be different. But clearly you are not doing that.

Could you try my code and see which result you get?

3 Likes

I don’t think Sven’s post is correct, see my other post.

1 Like

Your code works just like you described.
Probably I’d messed up some code and that was my problem.
Thank you guys for your help.

2 Likes

I finally found why such a thing happened to me!

The problem is that I misspelled the module name in this way:

  • a.script: mod = require "test.mod"
  • b.script: mod = require "test.Mod"

The only difference here is capital and small “M”. Actually you can also write something like mOd or MOD, etc. Looks like each combination of capital and small letters (while name spelled correctly) “creates” a new instance.
It doesn’t throw any errors, it just creates a new instance of module with default values (we can put print(M) before return M in module code and see that the table was created two times with different addresses).

Is it a bug or situation which should be kept in mind?

Interesting. It’s not really a bug, but I’d say it’s something that should be prevented or warned about either on an engine level or Lua level. It’s possible to prevent or warn about it from Lua by replacing the require function or by creating a custom loader (package.loaders) that would do a case insensitive check the of the package.loaded table for an already existing module instance and return that.

1 Like