Выполнять загруженные файлы Lua в определенной области

Я использую Lua в качестве формата конфигурации для моего проекта. Давайте предположим, что у меня есть следующий надуманный пример, мы будем называть conf.lua:

title = "Lorem Ipsum"
author = "John Doe"
date = "01 January 2000"

Теперь, тривиально, я могу, конечно, загрузить этот файл так:

dofile("conf.lua")

Однако проблема в том, что эти определения задаются в глобальном пространстве имен, что мне не нужно. Кроме того, это затрудняет доступ к различным переменным в целом (например, цикл по набору переменных конфигурации). Одним из решений будет переписать conf.lua вот так:

local conf = {
    title = "Lorem Ipsum",
    author = "John Doe",
    date = "01 January 2000"
}

return conf

и, в свою очередь, загрузить conf.lua со следующим кодом:

local configuration = dofile("conf.lua")

Тем не менее, это не идеал, я думаю, очевидные причины. Это требует от моих пользователей отслеживать запятые, чтобы написать local, чтобы не забыть вернуть стол в конце. Что было бы хорошо, если бы был какой-то способ вызвать conf.lua выполнить с пользовательской областью некоторого вида.

1 ответ

Решение

Вместо того, чтобы использовать dofile, просто используйте loadfile,

loadfile позволяет указать среду, в которой будет выполняться загруженный чанк. Установка этого параметра в качестве пустой таблицы позволяет помещать в эту таблицу значения upvalue.

local function load_conf ()
    local env = {}

    local chunk, err = loadfile('conf.lua', 'bt', env)

    if not err then
        chunk()
    end

    return env, err
end

local conf, conf_err = load_conf()

print(conf_err)
print(conf.title, conf.author, conf.date)

loadfile использует аналогичные правила, как load за исключением того, что он загружает кусок из файла, или stdin вместо строки или функции построения строки.


Обратите внимание, что setfenvтребуется для обратной совместимости с Lua 5.1. Вы должны использовать следующее (или что-то подобное) перед выполнением загруженного чанка.

if setfenv then
    setfenv(chunk, env)
end

См. §8.1 - Изменения в языке справочного руководства Lua 5.2.


Наконец, рассмотрите возможность запуска своих блоков в защищенном режиме, используя pcall, чтобы файл конфигурации не приводил к сбою вашей основной программы.

Другие вопросы по тегам