Search code examples
lua

Accessing Lua Functions On Other Files


I want to separate my Lua file into two files: one that holds my functions and one that can call them. I have done a lot of research on this and all the resources I find do not explain this process very in depth. They typically say to use:

require "subsystem.lua"

I put this at the top of a new Lua file that is saved to the same directory and am not able to access anything.

Is there a config file I need to modify? Where is it?


Solution

  • Require the module

    The require function looks in a series of places to find a module. The exact list of places can be extensively customized by adjusting fields in the global table package.

    The easiest way to get a sense of how many places and names it uses when looking for a module is to look at the error message produced when require fails. For example, on my PC, Lua 5.1 says this:

    C:\Users\Ross>lua
    Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
    > require "xyzzy"
    stdin:1: module 'xyzzy' not found:
            no field package.preload['xyzzy']
            no file '.\xyzzy.lua'
            no file 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy.lua'
            no file 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy\init.lua'
            no file 'C:\Program Files (x86)\Lua\5.1\xyzzy.lua'
            no file 'C:\Program Files (x86)\Lua\5.1\xyzzy\init.lua'
            no file 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy.luac'
            no file '.\xyzzy.dll'
            no file '.\xyzzy51.dll'
            no file 'C:\Program Files (x86)\Lua\5.1\xyzzy.dll'
            no file 'C:\Program Files (x86)\Lua\5.1\xyzzy51.dll'
            no file 'C:\Program Files (x86)\Lua\5.1\clibs\xyzzy.dll'
            no file 'C:\Program Files (x86)\Lua\5.1\clibs\xyzzy51.dll'
            no file 'C:\Program Files (x86)\Lua\5.1\loadall.dll'
            no file 'C:\Program Files (x86)\Lua\5.1\clibs\loadall.dll'
    stack traceback:
            [C]: in function 'require'
            stdin:1: in main chunk
            [C]: ?
    > 
    

    After looking internally, the first "real" place it looks for xyzzy is in the file named .\xyzzy.lua. Then it tries a number of folders and names in the folder where lua.exe was found. Finally, it looks for a DLL that might offer it. The list of folders it searches for a .lua file is controlled by the string value in package.path. (The comparable list for DLLs in is package.cpath.) In that value, require will replace each ? with the module name, and then attempt to read the file. The first one to succeed is used.

    (The story here is slightly more complicated; you can create "searchers" that require will use to look in different places, and even change the order of the built-in searchers, but that is an advanced topic.)

    So just putting modules in Lua files in the current directory should work just fine, and adjusting package.path before calling require for your own modules can cover most quirks you will encounter.

    Create a module to require

    At its simplest, a module is just something that can be stored in package.loaded. Which is what require will do with it once it has been found, so that multiple calls to require will only search once and always return the same value.

    The traditional answer is for that "something" to be a table, usually mostly populated by functions that can be called, and occasionally having values. The math module is a good example: it provides lots of functions like sin and cos, along with the useful value math.pi and math.huge.

    Aside from being stored in a table, there is nothing special about a function in a module. Like any other function, it takes parameters and return zero or more values. The only real rule is that a module should not change or add global variables.

    So a very minimal module file can be as simple as:

    return { 
      addtwo = function(a, b) return a+b end,
      subtwo = function(x) return x-2 end,
    }
    

    which if stored as example.lua could be used like this:

    local example = require "example"
    print(example.addtwo(2,2)) -- 4
    print(example.subtwo(42))  -- 40
    

    A better module skeleton

    Sticking all your code in a single table declaration will not fly for most real cases. It does not scale well, and it makes it difficult to clearly express the relationship among functions that share state.

    -- simple modules
    
    -- capture the name searched for by require
    local NAME=...
    
    -- table for our functions
    local M = { }
    
    -- A typical local function that is also published in the 
    -- module table. 
    local function addtwo(a,b) return a+b end
    M.addtwo = addtwo
    
    -- Shorthand form is less typing and doesn't use a local variable
    function M.subtwo(x) return x-2 end
    
    return M
    

    Why no call to the module() function?

    Lua 5.1 included a standard function named module() intended to be used at the top of module implementations. Its use was never required, and a consensus formed fairly quickly that it was not as helpful an idea as hoped. It has since been deprecated.

    As a result, the simple skeleton I show above does not use it, and is portable to all versions of Lua since 5.1.