Dynamic File Loading

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Beelz
Party member
Posts: 234
Joined: Thu Sep 24, 2015 1:05 pm
Location: New York, USA
Contact:

Dynamic File Loading

Post by Beelz »

What I'm trying to do is look up all files in a specified folder, require them, and be able to use the functions from them...
I made a small .love as an example with all the files, but here's the code in question:

main.lua

Code: Select all

function love.load()
	local tbl = {}
	local files = love.filesystem.getDirectoryItems('testFolder')

	for _, f in ipairs(files) do 
		local x = 'testFolder/'.. f
		local y = require tostring(x)
		tbl[#tbl+1] = y
	end 

	print(#tbl)
	for i, v in ipairs(tbl) do
		print(tostring(i))
		--v:say(i.. ' Hi')
	end
end
Then I have a few of these in folder 'testFolder':

test1.lua

Code: Select all

local test = {}
function test.init()
	local t = {}
	function t:say(t)
		print(t)
	end
	return t
end
return test
Any help to what I'm doing wrong would be much appreciated, thanks.
Attachments
fileDirectories.love
(1.19 KiB) Downloaded 83 times

Code: Select all

if self:hasBeer() then self:drink()
else self:getBeer() end
GitHub -- Website
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Dynamic File Loading

Post by bartbes »

There's a few things:
  • Your module names are wrong (aka require doesn't take filenames)
  • Your require syntax is wrong (aka require is a function, not a magic keyword)
  • You're not using your own data structure properly
Let's go through them one by one:

You build module names using the directory, followed by a slash, then the filename, so for test1.lua, the resulting string is "testFolder/test1.lua", the correct module name for this file (which is what require takes) is "testFolder.test1". The simple solution here would be to first replace the slash by a dot, then instead of appending f, appending something like f:match("^(.+)%.lua") (which returns the name without the extension).

Also, require is a function like any other, and can indeed be re-implemented in lua! Thus, your syntax is wrong. If you're not thinking "But I've seen require 'stuff' before!", that's correct, lua allows you to skip parentheses on any one-argument function, if that argument is a literal string or table. In this case, it isn't, so the correct syntax will be require(x) (and the tostring is unnecessary, the module name is always a string).

Now the last point, if this worked, you're trying to call 'v:say()', but, at least in test1.lua, that corresponds to 'test:say()'. But test doesn't have a say function! You probably want to either call init, then call say on the result (so: v.init():say())) or move the say function to the test table itself.

Note that it may be more useful to store the required files with their name as the table's key, rather than a numeric one. There's also code for this floating around that will either do it recursively, and/or on any specific directory and/or lazily, perhaps there's something you can reuse?
pedrosgali
Party member
Posts: 107
Joined: Wed Oct 15, 2014 5:00 pm
Location: Yorkshire, England

Re: Dynamic File Loading

Post by pedrosgali »

Hey guys, sorry for the noobish question but could someone please explain why you should use dots in the require syntax for me? I keep seeing people say it but no one ever says why it is better.
I know for a fact that the require function can take a filepath with slashes as all my code uses it without error, I'm willing to go through and change all my slashes to dots but I'd really like to know why before I do.

Code: Select all

if not wearTheseGlasses() then
  chewing_on_trashcan = true
end
alloyed
Citizen
Posts: 80
Joined: Thu May 28, 2015 8:45 pm
Contact:

Re: Dynamic File Loading

Post by alloyed »

There isn't much of a practical reason to prefer dots to slashes if you're only using LOVE, but Lua in general uses dots because older windows/DOS programs expect backslashes instead of slashes. If you use dots, Lua will always pick the right separator for you, so there's no downside and only upside for using it.
pedrosgali
Party member
Posts: 107
Joined: Wed Oct 15, 2014 5:00 pm
Location: Yorkshire, England

Re: Dynamic File Loading

Post by pedrosgali »

I see, thanks for the clarification. Sorry about the off topic post. :)

Code: Select all

if not wearTheseGlasses() then
  chewing_on_trashcan = true
end
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Dynamic File Loading

Post by bartbes »

More importantly: require takes module names. Now, module names can be turned into file paths by replacing all dots by slashes and substituting the result for the question marks in the package path (which usually includes something like ?.lua, so it just appends the extension). This happens to allow slashes in module names, turning into a directory separator on the other end, but that is not the way it should be used. There are other ways to resolve modules, though, like from c libraries, those will never work with slashes. You can, for instance, load a love module like 'require "love.filesystem"', but you can't load it as "love/filesystem". Furthermore, require caches, but it caches on the exact module name, so mixing the two is just a bad idea.

In short: slashes work because of an implementation detail, dots are the right separator.

And one of these days I will make slashes an error in love because I get annoyed every time someone does this wrong.
pedrosgali
Party member
Posts: 107
Joined: Wed Oct 15, 2014 5:00 pm
Location: Yorkshire, England

Re: Dynamic File Loading

Post by pedrosgali »

Lol sorry to add to your frustration Bartbes. Again thanks for the clarification. :)

Code: Select all

if not wearTheseGlasses() then
  chewing_on_trashcan = true
end
Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests