5

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?

ggorlen
  • 44,755
  • 7
  • 76
  • 106
OT2O
  • 129
  • 2
  • 3
  • 8

3 Answers3

7

What you need to do is to return a table with the fields you want to access in subsystem.lua and then assign and use fields from that table in your main file. Something along these lines:

-- subsystem.lua

local function doSomething()
  -- do something useful here
end

local function doMore()
  -- do something else useful
end

return { doSomething = doSomething, doMore = doMore }

-- main.lua

local subsystem = require "subsystem" -- don't add `.lua` to your `require` call
subsystem.doSomething()
subsystem.doMore()

You may want to check Modules tutorial for details.

Paul Kulchenko
  • 25,884
  • 3
  • 38
  • 56
  • I was able to execute a function using this method. I was not able to return a value tho. I did have to put my substem.lua file into the defualt directory of my IDE tho.. How can I specify where to look and return a value? – OT2O Jan 07 '16 at 00:22
  • Make sure you have `return my-result` statement in your function. If that doesn't help, post a question with details of what you are trying to do. – Paul Kulchenko Jan 07 '16 at 01:37
7

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.

RBerteig
  • 41,948
  • 7
  • 88
  • 128
2

You probably want to use dofile instead of require.

dofile accepts file names, with paths.

require accepts module names and uses Lua search paths.

lhf
  • 70,581
  • 9
  • 108
  • 149
  • I like the idea of specifying where my file is because the location of the module has been confusing. Can you give me an example of calling a function on a separate file and getting a return value? – OT2O Jan 07 '16 at 00:35
  • @OT2O, files run with `dofile` can create global functions or return them in table for instance. Local functions are just that and cannot be seen outside the file. – lhf Jan 07 '16 at 00:39