lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Disclaimer: If this sounds like a blog post, that's because this is a blog post. (Should blog posts be tagged somehow? Say, [BP] or something?)

Lua's most overlooked feature is the require function. People assume it just loads a file and returns whatever it loaded. But it does a lot more than that.

For one, it implements a cache. You can require the same module over and over and it'll always return the same value. While this doesn't get overlooked often, I've seen people implement a cache on top of the standard require()... or attempt to reload a module with the standard require() .-. However, you can override this by fiddling with the contents of package.loaded.

For two, Lua's module system fully supports relative requires. This is one of the most overlooked features of Lua! I see people doing `local submod = require "thismod.submod"` all the time. That's not how you do it!

The proper way to do relative requires is:

thismod/init.lua
-----
local modname = ...
local submod = require(modname .. ".submod")
return {submod=submod}
-----

thismod/submod.lua
-----
return {
  helloworld = function() print("Hello World!") end
}
-----

Then, if you require "thismod", you can call thismod.submod.helloworld(). However, if you rename the thismod directory, and require the new directory name, it'll still work! Unlike when using hardcoded module names.

This "relative require" pattern is never mentioned in Programming in Lua, 3rd edition, which's a bit of a shame. It seems most Lua users don't know about this - even those who have worked with Lua extensively.

Don't make a searcher that supports `require"./name"`, as that'll just get cached as "./name". Make a searcher that supports `require(modname..".name")` instead, where `modname` comes from `...`.

This might be a new pattern to you, but it's a very useful pattern. I use it all the time with my oversized modules, precisely because it supports renaming.

There are a few other things require does that I'm not gonna go into. This isn't supposed to be a complete tutorial on modules - unlike the modules section of PiL (which I think should include this, however I don't have PiL 4 to check). But this is the basic idea of relative require.

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.