Alex Dean
Alex Dean

Reputation: 16075

Calling functions on require()d modules in Lua gives me "attempt to index local 'x' (a boolean value)"

I've read PIL and the ModulesTutorial on creating modules but I'm having trouble require()ing them correctly.

Here is my setup:

-- File ./lib/3rdparty/set.lua
local ipairs = ipairs
module( "set" )
function newSet (t)
  local set = {}
  for _, l in ipairs(t) do set[l] = true end
  return set
end

And:

-- File ./snowplow.lua
local set = require( "lib.3rdparty.set" )
module( "snowplow" )
local SUPPORTED_PLATFORMS = set.newSet { "pc", "tv", "mob", "con", "iot" }

Then if I run snowplow.lua:

lua: snowplow.lua:4: attempt to index local 'set' (a boolean value)
stack traceback:
  snowplow.lua:4: in main chunk
  [C]: ?

What am I doing wrong in my module definition - what is the boolean exactly? Also, if I append a return _M; at the bottom of my set.lua, then everything starts working - why?

Upvotes: 3

Views: 3935

Answers (2)

Daniel Tornaghi
Daniel Tornaghi

Reputation: 1

require("lib.moduleName")
local moduleName = moduleName

I'm not sure why Lua returns a boolean when you require a module on a different directory, but it seems the module is correctly set on the the global variable. So I simply used that and put it on a local variable with the same name.

Upvotes: 0

Egor Skriptunoff
Egor Skriptunoff

Reputation: 23737

true is usually returned by require if module function is not used inside module and module code doesn't return a value.
But anyway it seems strange.

-- file m0.lua
module'm0'


--file dir1\m1.lua
module'm1'


--file test.lua
print(require'm0')
print(m0)

print(require'dir1.m1')
print(m1)

for k,v in pairs(package.loaded) do
   if k:match'm%d' then print(k, v) end
end


--output
table: 0036C8C8
table: 0036C8C8
true
table: 0036B6B0
m0      table: 0036C8C8
m1      table: 0036B6B0
dir1.m1 true

So, you can simply use global variable set instead of local set assigned a value returned by require.


UPD :
It is recommended to avoid using module function and always return your table at the end of your module. In that case the whole picture is just fine:

-- file m0.lua
return 'string0'


--file dir1\m1.lua
return 'string1'


--file test.lua
print(require'm0')
print(m0)

print(require'dir1.m1')
print(m1)

for k,v in pairs(package.loaded) do
   if k:match'm%d' then print(k, v) end
end


--output
string0
nil
string1
nil
m0      string0
dir1.m1 string1

UPD2 :
Problem disappears if you replace module( "set" ) with module('lib.3rdparty.set').
So, each module must remember its relative path.
Now you could access it either by calling require'lib.3rdparty.set' or by reading global variable lib.3rdparty.set - the result would be the same.

Upvotes: 2

Related Questions