Reputation: 1098
I have two different lib written by lua, but with same function name.
How can I choose one of them without modify the lib source?
require ('A') --A lib
require ('B') --B lib
test() -- function from B
If I want test function from A, how can I do?
LuaJ loading two functions with the same name from two different LuaScripts
I found this, but I don't want modify the lib source code.
Save the function as different name, like this:
require ('A') --A lib
_G.testA = test
require ('B') --B lib
_G.testB = test
testA() -- function from A
testB() -- function from B
But if someday a new function name testA() or testB() it break again.
And I still need to change all exist test() to testA() or testB().
Is there any better way?
Upvotes: 1
Views: 1781
Reputation: 709
The code you have described
require ('A') --A lib
_G.testA = test
require ('B') --B lib
_G.testB = test
testA() -- function from A
testB() -- function from B
Is definitely one way to resolve your issue.
To avoid future issues you could put new functions inside a map
-- Example library.lua
-- Old code not in map
function my_old_func(params)
-- do some stuff
end
-- New code goes down here
local mylibrary = {}
function mylibrary:my_awesome_func(params)
my_old_func(params)
end
Upvotes: 0
Reputation: 4271
This is exactly the reason why Lua modules shouldn't set global variables, but instead export all its functions/variables in a table that gets returned via require
.
However, if your two modules are Lua modules, you can set a custom environment for each so that the global variables that the modules define end up in separate tables:
#!/usr/bin/lua
-- fallback implementation of package.searchpath for Lua 5.1
local searchpath = package.searchpath
-- not necessary if you have Lua 5.2+:
if not searchpath then
local delim = package.config:match( "^(.-)\n" ):gsub( "%%", "%%%%" )
function searchpath( name, path )
local pname = name:gsub( "%.", delim ):gsub( "%%", "%%%%" )
local msg = {}
for subpath in path:gmatch( "[^;]+" ) do
local fpath = subpath:gsub( "%?", pname )
local f = io.open( fpath, "r" )
if f then
f:close()
return fpath
end
msg[ #msg+1 ] = "\n\tnofile '"..fpath.."'"
end
return nil, table.concat( msg )
end
end
-- table for storing the environments for each module
local environments = {}
-- clone of the standard Lua searcher which sets a custom environment
-- for the loaded chunk and stores it in the environments table.
local function my_lua_searcher( modname )
local fpath, msg = searchpath( modname, package.path )
if not fpath then
return msg
end
local env = setmetatable( {}, { __index = _G } )
env._G = env
environments[ modname ] = env
local f = assert( loadfile( fpath, nil, env ) )
if setfenv then -- for Lua 5.1
setfenv( f, env )
end
return f, fpath
end
-- replace the Lua searcher (at index 2)
local searchers = package.searchers or package.loaders
-- if someone added to package.searchers, we have no way of knowing
-- which function is the Lua searcher we want to replace:
assert( #searchers == 4, "package.searchers has been modified" )
searchers[ 2 ] = my_lua_searcher
-- test it:
require( "A" )
require( "B" )
environments[ "A" ].test()
environments[ "B" ].test()
Upvotes: 3