如何将 Torch class 拆分为 Lua 岩石中的多个文件
How to split a Torch class into several files in a Lua rock
我最近协助开发了 Torch 的 Dataframe 包。由于代码库迅速翻倍,因此需要将 class 分成几个部分以便更好地组织和跟进 (issue #8)。
一个简单的测试-class 将是测试包根文件夹中的 test.lua 文件:
test = torch.class('test')
function test:__init()
self.data = {}
end
function test:a()
print("a")
end
function test:b()
print("b")
end
现在的 rockspec 很简单:
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',
}
}
为了让多个文件为单个 class 工作,有必要 return 最初创建的 class 对象并将其传递给子部分。上面的例子可以放到文件结构中:
\init.lua
\main.lua
\test-0.1-1.rockspec
\Extensions\a.lua
\Extensions\b.lua
luarocks install/make
根据'require'语法复制文件,其中每个.
表示一个目录,.lua
被省略,即我们需要更改rockspec至:
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'
}
}
以上将因此创建一个 test-文件夹,其中包与文件和子目录一起驻留。 class 初始化现在位于 return 对象 class 的 init.lua
中:
test = torch.class('test')
function test:__init()
self.data = {}
end
return test
子class 文件现在需要获取使用loadfile()
传递的class 对象(参见下面的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 filesystem 您应该将其添加到 rockspec 并且您仍然需要将每个文件添加到 rockspec 或它不会在扩展文件夹中)
- 识别路径文件夹
- 加载 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
如果您 运行 遇到同样的问题并且发现文档有点过于稀疏,我希望这对您有所帮助。如果您碰巧知道更好的解决方案,请分享。
我最近协助开发了 Torch 的 Dataframe 包。由于代码库迅速翻倍,因此需要将 class 分成几个部分以便更好地组织和跟进 (issue #8)。
一个简单的测试-class 将是测试包根文件夹中的 test.lua 文件:
test = torch.class('test')
function test:__init()
self.data = {}
end
function test:a()
print("a")
end
function test:b()
print("b")
end
现在的 rockspec 很简单:
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',
}
}
为了让多个文件为单个 class 工作,有必要 return 最初创建的 class 对象并将其传递给子部分。上面的例子可以放到文件结构中:
\init.lua
\main.lua
\test-0.1-1.rockspec
\Extensions\a.lua
\Extensions\b.lua
luarocks install/make
根据'require'语法复制文件,其中每个.
表示一个目录,.lua
被省略,即我们需要更改rockspec至:
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'
}
}
以上将因此创建一个 test-文件夹,其中包与文件和子目录一起驻留。 class 初始化现在位于 return 对象 class 的 init.lua
中:
test = torch.class('test')
function test:__init()
self.data = {}
end
return test
子class 文件现在需要获取使用loadfile()
传递的class 对象(参见下面的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 filesystem 您应该将其添加到 rockspec 并且您仍然需要将每个文件添加到 rockspec 或它不会在扩展文件夹中)
- 识别路径文件夹
- 加载 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
如果您 运行 遇到同样的问题并且发现文档有点过于稀疏,我希望这对您有所帮助。如果您碰巧知道更好的解决方案,请分享。