0Pricing
Lua Academy · Lección

Escritura de un archivo de módulo

Cree un módulo devolviendo una tabla de funciones desde un archivo .lua.

Escritura de un archivo de módulo es una lección gratuita de Lua Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Lua Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Lua Academy incluye 4 lecciones en total.

El patrón básico de módulo

El patrón estándar de módulos de Lua consiste en crear una tabla local M, añadirle funciones y valores, y devolverla al final. La tabla es la API pública del módulo. Todas las demás variables locales del archivo son privadas.

-- stringutils.lua
local M = {}

function M.trim(s)
  return s:match("^%s*(.-)%s*$")
end

function M.split(s, sep)
  local t = {}
  for p in s:gmatch("[^"..sep.."]+") do t[#t+1]=p end
  return t
end

return M

-- Usage:
-- local su = require("stringutils")
-- print(su.trim("  hello  "))

Estado privado

Las variables declaradas como local en el archivo del módulo son privadas: quienes llaman al módulo no pueden acceder a ellas. Las funciones del módulo pueden acceder al estado privado como upvalues. Este es el mecanismo de encapsulación de Lua.

-- counter.lua
local M = {}
local count = 0   -- private state

function M.increment(n)
  count = count + (n or 1)
end

function M.reset()
  count = 0
end

function M.get()
  return count
end

return M

Módulo con inicialización

Algunos módulos necesitan inicialización (configuración o conexiones). Coloque el código de inicialización a nivel del módulo (al principio del archivo) o en una función explícita M.init(). El enfoque a nivel del módulo se ejecuta una vez, cuando se requiere el módulo por primera vez; init() requiere una llamada explícita.

-- cache.lua
local M = {}
local store = {}   -- initialized at load time
local hits = 0
local misses = 0

function M.get(key)
  if store[key] ~= nil then
    hits = hits + 1
    return store[key]
  end
  misses = misses + 1
  return nil
end

function M.set(key, val) store[key] = val end
function M.stats() return {hits=hits, misses=misses} end

return M

Módulo con clase

Un módulo puede exportar una clase: una tabla con una función constructora. La tabla del módulo devuelta contiene la función new() y también puede servir como metatabla de la clase.

-- point.lua
local Point = {}
Point.__index = Point

function Point.new(x, y)
  return setmetatable({x=x, y=y}, Point)
end

function Point:distance(other)
  local dx, dy = self.x-other.x, self.y-other.y
  return math.sqrt(dx*dx + dy*dy)
end

function Point:__tostring()
  return string.format("(%g,%g)", self.x, self.y)
end

return Point

-- Usage:
-- local Point = require("point")
-- local p = Point.new(3, 4)

Constantes del módulo

Exporte constantes añadiéndolas a la tabla del módulo. Por convención, las constantes se escriben en mayúsculas. Como Lua no tiene const, técnicamente los usuarios pueden modificarlas, pero el uso de mayúsculas indica «no modificar».

-- colors.lua
local M = {}

M.RED   = {r=255, g=0,   b=0}
M.GREEN = {r=0,   g=255, b=0}
M.BLUE  = {r=0,   g=0,   b=255}
M.WHITE = {r=255, g=255, b=255}
M.BLACK = {r=0,   g=0,   b=0}

function M.toHex(c)
  return string.format("#%02X%02X%02X", c.r, c.g, c.b)
end

return M

Versionado de módulos

Incluya un campo de versión en el módulo. Quienes lo utilicen pueden comprobar la versión para garantizar la compatibilidad. Use versionado semántico (major.minor.patch).

-- mylib.lua
local M = {}
M._VERSION = "1.2.3"
M._NAME = "mylib"
M._DESCRIPTION = "My Lua library"

function M.hello(name)
  return "Hello, " .. (name or "World") .. "!"
end

return M

-- Usage:
local mylib = require("mylib")
print(mylib._VERSION)   -- 1.2.3
print(mylib.hello("Lua"))

Submódulos

Las bibliotecas grandes se dividen en submódulos. El módulo principal puede requerir y volver a exportar los submódulos, o cada submódulo puede utilizarse de forma independiente. Organice los archivos en directorios que correspondan a la ruta del módulo.

-- mylib/init.lua  (loaded by require("mylib"))
local M = {}

M.strings = require("mylib.strings")
M.tables  = require("mylib.tables")
M.math    = require("mylib.math")

M._VERSION = "2.0.0"

return M

-- Users can require the whole library:
-- local mylib = require("mylib")
-- mylib.strings.trim(...)

-- Or individual sub-modules:
-- local strs = require("mylib.strings")

Módulo con metatabla

Haga que un módulo sea invocable asignándole una metatabla con __call. Esto resulta útil para módulos que son principalmente funciones, pero que también tienen utilidades: la operación «principal» es la llamada y las utilidades son campos.

-- format.lua
local M = {}
setmetatable(M, {__call = function(_, fmt, ...)
  return string.format(fmt, ...)
end})

function M.pad(s, width, char)
  char = char or " "
  return string.rep(char, math.max(0, width - #s)) .. s
end

return M

-- Usage:
-- local fmt = require("format")
-- print(fmt("%.2f", 3.14))   -- 3.14
-- print(fmt.pad("42", 5))    --    42

Carga diferida de submódulos

Use __index para cargar submódulos de forma diferida, solo cuando se acceda a ellos por primera vez. Esto acelera el inicio de bibliotecas grandes con muchos submódulos.

-- biglib.lua
local M = {}
local submodules = {"strings", "tables", "math", "io"}

setmetatable(M, {
  __index = function(t, k)
    for _, name in ipairs(submodules) do
      if name == k then
        local mod = require("biglib." .. k)
        rawset(t, k, mod)
        return mod
      end
    end
    return nil
  end
})

return M

-- Loads biglib.strings only when accessed:
-- local lib = require("biglib")
-- lib.strings.trim(...)

Patrón de pruebas de módulos

Añada una función o un bloque de prueba al final del archivo del módulo, que se ejecute condicionalmente solo cuando el archivo se ejecute directamente (y no cuando se requiera). Así, las pruebas unitarias permanecen junto al código.

-- utils.lua
local M = {}

function M.clamp(v, lo, hi)
  return math.max(lo, math.min(hi, v))
end

-- Self-test: only runs when executed directly
if debug.getinfo(2, "S") == nil then
  -- Running as main script, not required
  print("Testing clamp...")
  assert(M.clamp(5, 0, 10) == 5)
  assert(M.clamp(-1, 0, 10) == 0)
  assert(M.clamp(15, 0, 10) == 10)
  print("All tests passed!")
end

return M

Comprobación rápida

¿Cuál es la forma estándar de definir un estado privado en un módulo de Lua?

Resumen: escritura de módulos

Resumen:

  • Patrón: local M = {} ... return M
  • Las variables locales del archivo son privadas; los campos de M forman la API pública
  • El código a nivel del módulo se ejecuta una vez, al requerirlo por primera vez
  • Exporte clases mediante un constructor en la tabla del módulo
  • Carga diferida de submódulos mediante __index
  • Incluya _VERSION para comprobar la compatibilidad

Preguntas frecuentes

¿La lección «Escritura de un archivo de módulo» es gratis?

Sí — el texto completo de «Escritura de un archivo de módulo» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Lua Academy, actualiza a CoddyKit PRO. El curso de Lua Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Escritura de un archivo de módulo»?

Cree un módulo devolviendo una tabla de funciones desde un archivo .lua. Practicas Lua Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Lua Academy?

No se requiere experiencia previa. Lua Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «Escritura de un archivo de módulo»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Lua Academy?

Sí. Cada lección de Lua Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. La función require
  2. Escritura de un archivo de módulo
  3. package.path y package.cpath
  4. Patrones de módulos y buenas prácticas
← Volver a Lua Academy