требуют, чтобы модуль
require
функция выглядит в серии мест, чтобы найти модуль. Точный список мест можно настроить, настроив поля в глобальной таблице package
.
Самый простой способ узнать, сколько мест и имен, которые он использует при поиске модуля, - это просмотреть сообщение об ошибке, возникшее после сбоя require
. Например, на моем компьютере, Lua 5.1 говорит, что это:
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]: ?
>
Посмотрев внутренне, то первый «реальный» место выглядит для xyzzy
находится в файле с именем .\xyzzy.lua
. Затем он пытается найти несколько папок и имен в папке, где было найдено lua.exe
. Наконец, он ищет DLL, которая может предложить его. Список папок, которые он ищет для файла .lua
, управляется строковым значением в package.path
. (Сопоставимый список для DLL в package.cpath
.) В этом значении require
заменит каждый ?
на имя модуля, а затем попытается прочитать файл. Используется первая для успеха.
(история здесь немного сложнее, вы можете создать «поисковик», что require
будет использовать для поиска в разных местах, и даже изменить порядок встроенные в поисковиках, но это сложная тема.)
Таким образом, просто размещение модулей в файлах Lua в текущем каталоге должно работать нормально, а настройка package.path
перед вызовом require
для ваших собственных модулей может охватывать большинство причуд, с которыми вы столкнетесь.
Создать модуль требует
В простейшем случае, модуль является только то, что можно хранить в package.loaded
.Это то, что require
будет делать с ним, как только оно будет найдено, так что несколько вызовов require
будут искать только один раз и всегда возвращать одинаковое значение.
Традиционный ответ - это то, что «что-то» должно быть таблицей, обычно большей частью населенной функциями, которые можно назвать, а иногда и имеющими значения. Хорошим примером является модуль math
: он предоставляет множество функций, таких как sin
и cos
, а также полезное значение math.pi
и math.huge
.
Помимо хранения в таблице, нет ничего особенного в функции в модуле. Как и любая другая функция, она принимает параметры и возвращает ноль или более значений. Единственное реальное правило заключается в том, что модуль не должен изменять или добавлять глобальные переменные.
Так оченьминимальная файл модуля может быть столь же простым, как:
return {
addtwo = function(a, b) return a+b end,
subtwo = function(x) return x-2 end,
}
, которые, если сохранены как example.lua
могут быть использованы, как это:
local example = require "example"
print(example.addtwo(2,2)) -- 4
print(example.subtwo(42)) -- 40
Лучший модуль скелет
Sticking весь ваш код в одном объявлении таблицы не будет летать для большинства реальных случаев. Он недостаточно масштабируется, и это затрудняет четкое выражение взаимосвязи между функциями, разделяющими состояние.
-- 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
Почему нет вызова функции module()?
В Lua 5.1 включена стандартная функция с именем module()
, предназначенная для использования в верхней части реализации модуля. Его использование никогда не требовалось, и консенсус сформировался довольно быстро, и это было не так полезно, как хотелось бы надеяться. С тех пор он устарел.
В результате простой скелет, показанный выше, не использует его и переносится для всех версий Lua с 5.1.
Благодарим вас за подробное объяснение. – OT2O