0Pricing
Lua Academy · Lección

Llamadas protegidas con pcall

Capture errores de forma segura mediante pcall e interprete sus valores de retorno.

Llamadas protegidas con pcall 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.

Conceptos básicos de pcall

pcall(f, ...) llama a la función f con los argumentos ... en modo protegido. Si f finaliza correctamente, pcall devuelve true seguido de todos los valores devueltos. Si f produce un error, pcall devuelve false seguido del mensaje de error. El programa continúa en ambos casos.

local function risky(x)
  if x < 0 then error("negative input: " .. x) end
  return math.sqrt(x)
end

local ok, result = pcall(risky, 9)
print(ok, result)    -- true  3.0

ok, result = pcall(risky, -1)
print(ok, result)    -- false  ...: negative input: -1

Captura de errores específicos

Compruebe el tipo del valor del error después de pcall para gestionar de forma distinta cada tipo de error. Los errores representados mediante tablas contienen datos estructurados; los errores de tipo cadena contienen un mensaje. Gestione siempre ambos casos.

local function op(errType)
  if errType == "table" then
    error({code=42, msg="structured error"})
  else
    error("plain string error")
  end
end

local ok, err = pcall(op, "table")
if not ok then
  if type(err) == "table" then
    print("Code:", err.code, "Msg:", err.msg)
  else
    print("String error:", err)
  end
end

Múltiples valores devueltos en caso de éxito

En caso de éxito, pcall devuelve todos los valores devueltos por la función protegida después del true inicial. Captúrelos con varias variables.

local function compute(a, b)
  return a + b, a * b, a - b
end

local ok, sum, product, diff = pcall(compute, 6, 4)
if ok then
  print("sum:", sum, "product:", product, "diff:", diff)
  -- sum: 10  product: 24  diff: 2
end

Anidamiento de pcall

Las llamadas a pcall pueden anidarse. Cada pcall crea un ámbito protegido independiente. Un error en un pcall interno es capturado por ese pcall interno, no por el externo. Esto permite implementar estrategias alternativas.

local function tryPrimary()
  error("primary failed")
end

local function tryFallback()
  return "fallback result"
end

local ok, result = pcall(tryPrimary)
if not ok then
  print("Primary failed:", result)
  ok, result = pcall(tryFallback)
end

if ok then print("Got:", result) end  -- fallback result

pcall con métodos

Para llamar a un método (sintaxis con dos puntos) mediante pcall, pase la función y el objeto como primer argumento. pcall(obj.method, obj, args...) o envuélvalo en una clausura.

local obj = {
  x = 10,
  compute = function(self, n)
    if n == 0 then error("zero divisor") end
    return self.x / n
  end
}

-- Pass method + self explicitly
local ok, v = pcall(obj.compute, obj, 2)
print(ok, v)   -- true  5.0

-- Or use a closure
ok, v = pcall(function() return obj:compute(0) end)
print(ok, v)   -- false  ...zero divisor

pcall para proteger operaciones de E/S

Envuelva las operaciones de E/S en pcall para capturar errores inesperados del sistema operativo. Devuelva siempre un par coherente de resultado y error, de modo que quienes llamen puedan gestionar los fallos correctamente.

local function safeRead(path)
  local ok, result = pcall(function()
    local f = assert(io.open(path, "r"))
    local content = f:read("a")
    f:close()
    return content
  end)
  if ok then return result
  else return nil, result
  end
end

local data, err = safeRead("config.txt")
if data then print("Read", #data, "bytes")
else print("Error:", err)
end

Patrón de reintento con pcall

Reintente una operación inestable (una solicitud de red o una escritura de archivo) hasta N veces, usando pcall para capturar los errores. En código real, espere entre los reintentos (o use corrutinas).

local function retry(fn, maxAttempts)
  local attempts = 0
  while attempts < maxAttempts do
    attempts = attempts + 1
    local ok, result = pcall(fn)
    if ok then
      print("Succeeded on attempt", attempts)
      return result
    end
    print("Attempt", attempts, "failed:", result)
  end
  error("all " .. maxAttempts .. " attempts failed")
end

local n = 0
retry(function()
  n = n + 1
  if n < 3 then error("not ready") end
  return "done"
end, 5)

Captura de pcall en una tabla

Cuando use pcall en un bucle, almacene los resultados en una tabla para analizarlos posteriormente. Esto resulta útil en operaciones por lotes en las que desea procesar todos los elementos y recopilar los errores en lugar de detenerse ante el primer fallo.

local jobs = {10, -5, 25, 0, 16}
local results = {}

for _, n in ipairs(jobs) do
  local ok, v = pcall(function()
    if n < 0 then error("negative") end
    return math.sqrt(n)
  end)
  results[#results+1] = {input=n, ok=ok, value=v}
end

for _, r in ipairs(results) do
  if r.ok then
    print(r.input, "->", string.format("%.3f", r.value))
  else
    print(r.input, "-> ERROR:", r.value)
  end
end

pcall frente a xpcall

pcall captura el error, pero solo le proporciona el valor del error. xpcall permite proporcionar una función controladora de mensajes que se ejecuta mientras la pila aún está intacta, lo que permite obtener trazas de la pila. Elija xpcall cuando necesite trazas.

-- pcall: simple, no traceback
local ok1, err1 = pcall(function()
  error("simple error")
end)
print(err1)   -- only the error message

-- xpcall: with traceback handler
local ok2, err2 = xpcall(
  function() error("traced error") end,
  function(e) return debug.traceback(e, 2) end
)
print(err2)   -- full stack trace

Convención de retorno de pcall

Use pcall como base de una API coherente: devuelva siempre value si la operación tiene éxito o nil, errorMessage si falla. Estructure sus funciones de esta manera para que quienes llamen sepan siempre qué esperar.

local function loadJSON(path)
  local ok, result = pcall(function()
    local f = assert(io.open(path, "r"))
    local text = f:read("a")
    f:close()
    -- Fake JSON parse for demo
    return {data = text, path = path}
  end)
  if ok then return result
  else return nil, result
  end
end

local data, err = loadJSON("data.json")
if data then print("Loaded:", data.path)
else print("Failed:", err)
end

Comprobación rápida

¿Qué devuelve pcall cuando la función protegida finaliza correctamente?

Resumen: pcall

Resumen:

  • pcall(f, ...) → true, results... o false, err
  • Compruebe el primer valor devuelto para determinar si la operación tuvo éxito o falló
  • En caso de éxito, los valores devueltos adicionales aparecen después de true
  • pcall anidado: cada llamada captura sus propios errores de forma independiente
  • Patrón de reintento: use un bucle con pcall para operaciones inestables
  • Use xpcall cuando necesite trazas de la pila

Preguntas frecuentes

¿La lección «Llamadas protegidas con pcall» es gratis?

Sí — el texto completo de «Llamadas protegidas con pcall» 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 «Llamadas protegidas con pcall»?

Capture errores de forma segura mediante pcall e interprete sus valores de retorno. 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 «Llamadas protegidas con pcall»?

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 error()
  2. Llamadas protegidas con pcall
  3. xpcall y gestores de mensajes
  4. Objetos de error estructurados
← Volver a Lua Academy