2012-01-06 25 views
6

Tengo una función lua que toma múltiples parámetros y devuelve tantos valores como parámetros hay. Cada valor de retorno corresponde a un parámetro. Como ejemplo, consideremos una función que lee el valor de un par clave/valor a partir de una base de datos:Práctica recomendada para devolver un error de una función lua que devuelve valores múltiples

val1, val2, val3 = my_function("key1", "key2", "key3"); 
val1 = my_function("key1"); 

¿Cuál es la mejor manera de devolver un error de my_function? (por ejemplo, si la "clave" suministrada no es válida)

Entiendo que una forma es devolver dos valores en caso de error, nil y una cadena de error. ¿Es este el mejor enfoque? Por ejemplo:

val1, val2, val3 = my_function("key1", "key2", "key3"); 
if val1 then 
    -- Use val1, val2, and val3. 
else 
    print("ERROR: " .. val2); 
end 

Editar

algunos puntos adicionales:

  1. El script lua se está ejecutando dentro de un programa C usando lua_pcall().
  2. El programa C no debe interrumpirse si el script falla.
  3. my_function() se implementa en C
  4. Cuando my_function() falla, sino que también debe devolver un código de error (o mensaje) que indica la razón por la que falló.

Respuesta

6

La forma estándar de tirar errores en Lua es a través de la función de error (manual, api) o por medio de assert (que utiliza internamente error de todos modos).

Como su función está en C, debe llamar al lua_error para obtener el mismo efecto.

Pero tenga en cuenta que su función ahora es "insegura". Si no modificado, el siguiente código hará el equivalente de "lanzar una excepción" y así detener el programa, si key1, clave2 o key3 son "errónea":

val1, val2, val3 = my_function("key1", "key2", "key3") 

A veces es buena idea dejar que el programa "sólo para dormir "si las entradas son incorrectas. Dependiendo de su configuración, el usuario recibirá un mensaje con el último error y un seguimiento de pila, o algo similar.

Si "dejar que el programa de choque" no es una opción, se puede hacer el equivalente a lo rodea con un bloque "try-catch" mediante el uso de la función pcall, y añadiendo una nueva variable llamada ok:

ok, val1, val2, val3 = pcall(my_function, "key1", "key2", "key3") 
if ok then 
    -- Use val1, val2, and val3. 
else 
    print("ERROR: " .. val1) -- notice that we use val1 here, not val2 
end 

Tenga en cuenta que no tiene que poner pcall exactamente en la parte superior de my_function. Al igual que con las excepciones, la recuperación de errores puede ocurrir más arriba en la cadena de llamadas: en la función que llama al my_function, o la función que llama a esa, etc.Por ejemplo, si se llama a my_function de una función llamada parent, y el padre de una llamada grandParent, usted puede hacer esto:

-- parent is "insecure" since my_function is "unprotected" 
function parent(key1, key2) 
    local val1, val2, val3 = my_function(key1, key2, "key3") 
    return val1, val2, val3 
end 

-- grandParent calls parent in a "safe" way 
function grandParent() 
    local ok, val1, val2, val3 = pcall(parent, "key1", "key2") 
    if ok then 
    -- Use val1, val2, and val3. 
    else 
    print("ERROR: " .. val1) 
    end 
end 
+0

He editado la pregunta para aclarar algunos puntos. Dado que la secuencia de comandos lua (que eventualmente llama a 'my_function()') se ejecuta desde C con 'lua_pcall()', ¿debe 'my_function()' devolver una variable "ok" como describió anteriormente? (por ejemplo, 'ok, val1, val2, val3 = my_function()'). – Ben

+0

@Ben, sí, incluiría un valor 'ok' adicional, que parece ser la manera más limpia. También recomendaría una revisión en el diseño; ya que ambas funciones están en C, probablemente será más simple (y más rápido) olvidarse de Lua y simplemente hacer todo en C. – kikito

+0

@kikto, gracias por aclarar. En este caso, definitivamente tiene sentido para mí usar lua (o un equivalente) para extender el producto. – Ben

0

La práctica habitual es lanzar errores cuando el programa no puede recuperarse (identificador de archivo mal, por ejemplo,) y errores de señal cuando puede recuperarse (archivo no encontrado, por ejemplo). En su caso, creo que devolver nil en busca de claves no válidas es la mejor manera.

+0

Si quiero que my_function() también devuelva el motivo por el que falló, ¿defiende que si 'val1, val2, val3 = my_function()' falla, 'val1' debería ser' nil' y 'val2' debería ser el código de error /¿mensaje? – Ben

+0

@Ben, no, pensé que la única razón era "clave inválida". – lhf

Cuestiones relacionadas