Как разделить класс Torch на несколько файлов в Lua Rock

В последнее время мне оказали помощь в разработке пакета Dataframe для Torch. Поскольку база кода быстро удвоилась, необходимо разделить класс на несколько разделов для лучшей организации и контроля ( выпуск № 8).

Простым классом test будет файл test.lua в корневой папке пакета test:

test = torch.class('test')
function test:__init()
  self.data = {}
end

function test:a()
  print("a")
end

function test:b()
  print("b")
end

Теперь для этого просто необходимо указать:

package = "torch-test"
 version = "0.1-1"
 source = {
    url = "..."
 }
 description = {
    summary = "A test class",
    detailed = [[
       Just an example
    ]],
    license = "MIT/X11",
    maintainer = "Jon Doe"
 }
 dependencies = {
    "lua ~> 5.1",
    "torch >= 7.0",
 }
 build = {
  type = 'builtin',
  modules = {
      ["test"] = 'test.lua',
  }
 }

1 ответ

Решение

Чтобы несколько файлов работали на один класс, необходимо вернуть изначально созданный объект класса и передать его подразделам. Приведенный выше пример может быть помещен в структуру файла:

\init.lua
\main.lua
\test-0.1-1.rockspec
\Extensions\a.lua
\Extensions\b.lua

luarocks install/make копирует файлы в соответствии с синтаксисом 'require', где каждый . означает каталог и .lua опущено, т.е. нам нужно изменить горную спецификацию на:

package = "torch-test"
 version = "0.1-1"
 source = {
    url = "..."
 }
 description = {
    summary = "A test class",
    detailed = [[
       Just an example
    ]],
    license = "MIT/X11",
    maintainer = "Jon Doe"
 }
 dependencies = {
    "lua ~> 5.1",
    "torch >= 7.0",
 }
 build = {
  type = 'builtin',
  modules = {
      ["test.init"] = 'init.lua',
      ["test.main"] = 'main.lua',
      ["test.Extensions.a"] = 'a.lua',
      ["test.Extensions.b"] = 'b.lua'
    }
  }

Таким образом, приведенное выше создаст тестовую папку, в которой пакеты находятся вместе с файлами и подкаталогами. Инициализация класса теперь находится в init.lua который возвращает объект класса:

test = torch.class('test')
function test:__init()
  self.data = {}
end
return test

Файлы подкласса теперь должны забрать объект класса, который передается с использованием loadfile() (увидеть init.lua файл ниже). a.lua теперь должно выглядеть так:

local params = {...}
local test = params[1]
function test:a()
  print("a")
end

и аналогичное дополнение для b.lua:

local params = {...}
local test = params[1]
function test:b()
  print("b")
end

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

  • Поиск всех доступных расширений и их загрузка (Примечание: требуется файловая система lua, которую вы должны добавить в rockpec, и вам все равно нужно добавить каждый файл в rockpec, иначе его не будет в папке Extensions)
  • Определяет папку путей
  • Загружает main.lua
  • Работает в чистой тестовой среде без установленного пакета

Код для init.lua:

require 'lfs'

local file_exists = function(name)
   local f=io.open(name,"r")
   if f~=nil then io.close(f) return true else return false end
end

-- If we're in development mode the default path should be the current
local test_path = "./?.lua"
local search_4_file = "Extensions/load_batch"
if (not file_exists(string.gsub(test_path, "?", search_4_file))) then
  -- split all paths according to ;
  for path in string.gmatch(package.path, "[^;]+;") do
    -- remove trailing ;
    path = string.sub(path, 1, string.len(path) - 1)
    if (file_exists(string.gsub(path, "?", "test/" .. search_4_file))) then
      test_path = string.gsub(path, "?", "test/?")
      break;
    end
  end
  if (test_path == nil) then
    error("Can't find package files in search path: " .. tostring(package.path))
  end
end

local main_file = string.gsub(test_path,"?", "main")
local test = assert(loadfile(main_file))()

-- Load all extensions, i.e. .lua files in Extensions directory
ext_path = string.gsub(test_path, "[^/]+$", "") .. "Extensions/"
for extension_file,_ in lfs.dir (ext_path) do
  if (string.match(extension_file, "[.]lua$")) then
    local file = ext_path .. extension_file
    assert(loadfile(file))(test)
  end
end

return test

Я надеюсь, что это поможет, если вы столкнетесь с той же проблемой и найдете документацию немного скудной. Если вам случится узнать лучшее решение, пожалуйста, поделитесь.

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