circular dependency management

Place to get help with not working mods / modding interface.
User avatar
hgschmie
Fast Inserter
Fast Inserter
Posts: 142
Joined: Tue Feb 06, 2024 5:18 am
Contact:

circular dependency management

Post by hgschmie »

Hi,

so I have two files, A.lua and B.lua:

A.lua:

Code: Select all

local A = {}

-- manage circular dependencies
local _pkgname = ...
package.loaded['__' .. script.mod_name .. '__/' .. _pkgname:gsub('%.', '/') .. '.lua'] = A
-- manage circular dependencies

local B = require('some.thing.B')
B.lua:

Code: Select all

local B = {}

-- manage circular dependencies
local _pkgname = ...
package.loaded['__' .. script.mod_name .. '__/' .. _pkgname:gsub('%.', '/') .. '.lua'] = B
-- manage circular dependencies

local A = require('some.thing.A')
This works fine. No matter which file is required first (A or B), it loads the other file and then continues without falling into a recursive loop.

But it is ugly. Is there really no better way to create the loaded key than doing this dance:

Code: Select all

local _pkgname = ...
package.loaded['__' .. script.mod_name .. '__/' .. _pkgname:gsub('%.', '/') .. '.lua'] = ... the main table of the file ...
It would be nice if we can have some function to call from a file with the `...` as argument that returns the needed key for the package.loaded table. As the game itself does that, such a function must exist somewhere.
Natha
Filter Inserter
Filter Inserter
Posts: 285
Joined: Sun Mar 15, 2015 1:48 pm
Contact:

Re: circular dependency management

Post by Natha »

What do you want to achieve exactly?
User avatar
hgschmie
Fast Inserter
Fast Inserter
Posts: 142
Joined: Tue Feb 06, 2024 5:18 am
Contact:

Re: circular dependency management

Post by hgschmie »

Natha wrote: Mon Sep 29, 2025 1:38 pm What do you want to achieve exactly?
Well, ideally I could do something like this:

Code: Select all

local A = {}
package.loaded[package.key(...)] = A
using a hypothetical `package.key` functionthat would create the correct key from the varargs that get passed in.

In vanilla lua, you can do that:

Code: Select all

local A = {}
package.loaded[...] = A
but that does not work in Factorio because the `package` module has been replace with a special implementation (if you open it in a debugger, it shows the keys which contain the module name and the path with '/' and the '.lua' ending).

I can emulate it just fine and it works great (and I found a one-liner variant as well) but it seems cumbersome (and reminds me of perl a lot).


Why am I doing this? To avoid hacks like this: https://github.com/Afforess/Factorio-St ... #L583-L592

My internal fork looks like this:

Code: Select all

local Area = { __class = 'Area', __index = require('stdlib.core') }
setmetatable(Area, Area)

package.loaded['__' .. script.mod_name .. '__/' .. (...):gsub('%.', '/') .. '.lua'] = Area

local Position = require('stdlib.area.position')

Code: Select all

local Position = { __class = 'Position', __index = require('stdlib.core') }
setmetatable(Position, Position)

package.loaded['__' .. script.mod_name .. '__/' .. (...):gsub('%.', '/') .. '.lua'] = Position

local Area = require('stdlib.area.area')
and avoids the hack. :-)
Post Reply

Return to “Modding help”