【问题标题】:Breaking a single lua function into small files将单个 lua 函数分解为小文件
【发布时间】:2014-07-17 00:29:03
【问题描述】:

我正在使用 Lua 和 LÖVE 开发一款游戏。

我更喜欢基于闭包的 OOP 方法,每个关卡都是一个函数的新实例,其中包含运行游戏所需的所有局部变量和函数。

我想把这个单一的功能分解成多个文件。我目前的解决方案与我在这里所做的类似:concatenating multiple files into a single one - 但我真的认为这还不理想。

例如,我将有一个 load.lua 文件,其中包含来自下面 sn-p 的 self.load 函数。

giant函数的代码sn-p参考如下:

levelSetup = function()
local time = 60
local timer = time
local timerIsRunning = true
local danger = 10
local handSize = 2
local itemsLeft = handSize
local curHand = 0
local lastHand = 10
local multiplier = 1
local self = {}

------------------------------------------------------
-- Initialize Values based on level Creation
------------------------------------------------------
self.load = function()
  if curLevel.time == 1 then
    time = 60
  elseif curLevel.time == 2 then
    time = 40
    multiplier = multiplier*1.5
  else
    time = 20
    multiplier = multiplier*2
  end

  if curLevel.danger == 1 then
    danger = 10 --low catastrophe chance
  elseif curLevel.danger == 2 then
    danger = 30 --medium chance
    multiplier = multiplier*1.5
  else
    danger = 50--high chance!
    multiplier = multiplier*2
  end

  if curLevel.handSize == 1 then
    handSize = 2
  elseif curLevel.handSize == 2 then
    handSize = 3
    multiplier = multiplier*1.5
  else
    handSize = 4
    multiplier = multiplier*2
  end
  itemsLeft = handSize
  timer = time
  self.nextHand()
end

  return self
end

什么是最好的解决方案?

【问题讨论】:

    标签: lua code-cleanup love2d


    【解决方案1】:

    将代码分解成更小的文件总是好的。如果你打算这样做,一个优雅的解决方案(以我的拙见)将使用return 语句。这是 Lua 生态系统中的very common and preferred practice

    假设你的项目由几个子模块组成,分别是submoduleA.luasubmoduleB.luasubmoduleC.lua。这些子模块中的每一个都包含一些专门的代码(它可以是单个函数,也可以是一组函数,但让我们假设每个子模块中都有一个函数)。

    除了这些子模块之外,您还有一个 主文件(名为 main.lua),您希望从中调用和使用子模块中定义的函数。 p>

    submoduleA.lua 将包含一些名为 funcA 的函数的定义。这个函数可以有自己的局部变量,并使用 upvalues,这没问题。理想情况下,这个 funcA 应该在 submoduleA.lua 文件中声明为本地,以解决范围问题。然后,在文件末尾,使用return 语句返回函数本身。

    -- declaring upvalues, if any
    local upvalue1 = ... -- placeholder code
    local upvalue2 = ... -- placeholder code
    
    -- function definition
    local function funcA(arg1, arg2, ...)
      -- some code
    end
    
    return funcA -- at the end of the file
    

    submoduleB.luasubmoduleC.lua

    也是如此

    然后,在 main.lua 文件中,您可以使用require 语句轻松调用子模块中定义的函数。注意require 的一个细节,您不需要添加扩展名“.lua”,因为它会自动添加(文档对此非常明确)。

    local funcA = require ('submoduleA') 
    local funcB = require ('submoduleB')
    local funcC = require ('submoduleC')
    

    就是这样。同样,这对于 Lua 来说是一种非常常见的模式。在编写自己的项目/库时,我使用类似的技术,尤其是当代码跨越多个文件时。请参阅JumperFloodFill,以供参考。

    我还将推荐那些额外的讲座以进行深入反思,因为它们指出了在编写 Lua 模块时要采用的一些非常好的策略:

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      必须在单个块中定义函数。但是,使用load 函数,您可以使用多个源组装您的块数据。例如:

      function closuredef( ... )
        local modules, n = { ... }, select( "#", ... )
        local index = -1
        local function reader()
          index = index + 1
          if index == 0 then -- chunk prefix
            return "local self = {};"
          elseif index == n+1 then -- chunk suffix
            return "\nreturn self"
          else -- read specified Lua files and add them to the chunk data
            local modname = modules[ index ]
            if modname ~= nil then
              local fname = assert( package.searchpath( modname, package.path ) )
              local file = assert( io.open( fname, "r" ) )
              local data = assert( file:read( "*a" ), "could not read '"..fname.."'" )
              file:close()
              return data
            end
          end
        end
        return assert( load( reader, "=closuredef" ) )
      end
      
      levelSetup = closuredef( "level.variables", "level.load" )
      

      这个示例实现使用package.searchpath(这是 Lua 5.2 中的新功能)来制作 指定 Lua 文件更方便。如果你还在使用 Lua 5.1,你可以使用绝对文件名或者实现你自己的package.searchpath 函数。有关示例,请参阅 hereherehere

      我不确定这是解决您问题的最佳方法,例如您将很难将错误消息中的行号映射到真正的错误位置...

      【讨论】:

      • 对于这个特定的问题,绝对是最好的答案——尽管调试困难。这种“难以清理”的情况可能表明我需要重新考虑我的代码。
      猜你喜欢
      • 2016-08-26
      • 1970-01-01
      • 2013-05-13
      • 2020-01-12
      • 2015-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-07
      相关资源
      最近更新 更多