A la hora de lanzar un juego o una aplicación, una de las cosas más frustantes tanto para el Coder como para el usuario, es ver el típico mensaje de error parecido a este:error: fichero.lua:239: attempt to perform arithmetic on a nil value
Y que la aplicación finalice de forma brusca.
Desde luego, hay errores, los llamados "fatales", que por mucho que nos empeñemos harán que no podamos seguir nuestra aplicación, pero otros, aunque el intérprete lua haga terminar el script, nosotros sí podríamos volver a tomar el control y continuar con la aplicación o volver a un punto anterior.
Errores "fatales" (no podemos retormar la aplicación después de ellos):
Errores en los que sería posible retomar la aplicación:
Espero que hayáis captado la idea.
Lenguajes compilados como C++, FreePascal, Visual Basic, y otros interpretados como PHP o Python, tienen una forma más elegante y efectiva de tratar las excepciones (se le suele llamar así a los manejos de errores), Lua lo hace de una forma poco usual y bastante "cutre" a mi modo de ver, pero es lo que toca, así que no nombraré las técnicas "normales" y me centraré en la técnica "a lo Lua", para no confundir (y daros pena xD). Comencemos pues:
function LanzarError(num) local total = num + nil print("LanzarError: El total es: ", total) end LanzarError(33) print ("continuamos la marcha...")
Si ejecutamos este código, fallará en la linea 2, y nunca imprimirá "continuamos la marcha...", porque estamos sumando 33 + nil, lo que nos daría el siguiente error:
error: script.lua:2: attempt to perform arithmetic on a nil value
Bueno, vamos a suponer que nosotros sabemos que aunque ese total esté erróneo, podemos continuar la aplicación. Recordad que DEBÉIS TENER UN PLAN ALTERNATIVO en caso de error, sino, de nada sirve continuar si 3 lineas después vamos a usar esa variable que está mal y nos va a dar de nuevo error.
Ahora es cuando la sentencia pcall(), llega al rescate. Mismo código usándola:
function LanzarError(num) local total = num + nil print("LanzarError: El total es: ", total) end local ok ok = pcall(LanzarError, 33) if not ok then print("Hubo un error al sumar el total. Disfruten las molestias.") end print("continuamos la marcha...")
Ahora tenemos la siguiente salida:
Hubo un error al sumar el total. Disfruten las molestias. continuamos la marcha...
Si os fijáis, el programa ha continuado y lo mejor de todo es que no se ha visto "el típico mensaje de error", sino uno que le hemos puesto. Esto da a nuestras aplicaciones un acabado más profesional. Es decir También hemos personalizado el error, es más, no podríamos haber puesto ningún mensaje.
Comentando el código anterior, si os fijáis, pcall(), tiene como primer parámetro la función a la cual se llama y los siguientes parámetros son los que se le envían a la función llamada, en este caso, sólo enviamos un parámetro, el núm. 33. pcall() retorna más de un parámetro, pero eso lo vamos a ver un poco más adelante, de momento quedaros con que envía como primer parámetro true si todo fue bien y false si hubo un error.
Personalizando MEJOR nuestros errores:
Lo cierto, es que más que el mensaje de "disfruten las molestias", es conveniente indicar el script, la linea y la descripción del error, tal y como lo hace Lua por defecto, esto nos permite localizar rápidamente los errores. Pero vamos a ver la forma de hacer esto "más bonito" y no como una simple linea.
Como dije anteriormente, pcall() devuelve más de un valor. Si no hay error, devuelve true como primer parámetro y el siguiente parámetro o parámetros, son los que enviaría la función normalmente si es que devuelve alguno. En caso de error, el primer parámetro será false, y el segundo (IMPORTANTE), es el texto con el error. Si volvemos al ejemplo inicial, este sería el texto que contendría el segundo parámetro (se omite el primer "error: ").
script.lua:2: attempt to perform arithmetic on a nil value
Ojo con ese segundo valor que unas veces puede ser esa cadena y otra lo que devuelva vuestra función, tenedlo en cuenta.
He creado una función que podéis usar en vuestros proyectos, descompone esa cadena en una tabla con 3 elementos:
Teniendo estos datos separados, podéis presentar los errores de forma "bonita", con vuestra fuente, color, un fondo especial para errores, etc.
Esta es la función extractError():
function extractError(err) --[[ 1.0.1 : 2010-06. By GorristeR. Under GPL3 License. Desglosa en una tabla un mensaje de error devuelvo por pcall(). Dicha tabla 3 elementos: script: Nombre del script donde se produjo el error line: Linea del error text: Texto descriptivo del error --]] local result = {} local pos1, pos2 pos1 = string.find(err, ":") pos2 = string.find(err, ":", pos1+1) result.script = string.sub(err, 1, pos1-1) result.line = string.sub(err, pos1+1, pos2-1) result.text = string.gsub(string.sub(err, pos2+1), "^%s*(.-)%s*$", "%1") return result end
Y aquí está el último ejemplo:
function LanzarError(num) local total = num + nil print("LanzarError: El total es: ", total) end ok, msgError = pcall(LanzarError, 33) if not ok then myError = extractError(msgError) print("Hubo un error al sumar el total. Disfruten las molestias.") print("Script : "..myError.script) print("Linea : "..myError.line) print("Error : "..myError.text) print("Consulte manual online para buscar una solución") end print("continuamos la marcha...")
No creo que el código requiera mucha explicación. Como veis podéis personalizar un error como queráis.
Hubo un error al sumar el total. Disfruten las molestias. Script : script.lua Linea : 2 Error : attempt to perform arithmetic on a nil value Consulte manual online para buscar una solución continuamos la marcha...
En la siguiente entrega, Os enseñaré una forma un poco diferente, y más "elegante" de tratar los errores en Lua, seguramente uséis esa nueva forma en vez de ésta, pero siempre es bueno saber de más ;-).
Comentarios se agradecen y motivan a seguir haciendo tutoriales.
LuaDiE: Crea en Lua sin teclear código. Compatible HM7, HMv2, LuaPlayer, LuaDEV y PGE.
Genial.
Da gusto ver aportes con tanta calidad. Muchas gracias gorrister. Me encargo de ponertelo en portada ;-)
Un saludo crack.
Que por cierto, para usar la
Que por cierto, para usar la librería ¿que tengo que copiar?
Más que librería,
es una función. Y es esta:
Para recibir ayuda por parte de otros usuarios más rápidamente, recomendamos que pongas títulos descriptivos y no utilices abreviaturas (estilo MSN) en tus post de los foros. Recuerda que accediendo al Manual del perfecto forero y las Normas de la Comunidad aprenderas trucos para resolver tus dudas antes.
No preguntes por MP, mejor pregunta aquí.
Ya ya, entonces para usarlo
Ya ya, entonces para usarlo si eso tengo que copiar esa funcion, ¿Verdad?
Gracias por estos tutoriales
Vaya tuto verdad, gracias aun que no entiendo muy bien, ya que tengo poco aprendiendo lua XD un saludo
Que buen
tutorial, de verdad muchas gracias, esperamos mas tutoriales de este tipo.
Gracias, un saludo.
¡Tio, asustas! Tu has nacido
¡Tio, asustas! Tu has nacido para esto.
Grandioso aporte.
ORALE man gracias por el tuto
ORALE man gracias por el tuto n.n
me servira para proximos proyectos :D
Esto
se agradece bastante pspgorrister muchas Gracias lastima que no tiene tanta "popularidad" como es un post OFFTOPIC
espero mas tutos :)
Salu|2|
\\m// ₪₪₪₪₪₪-- ☠ ☠ ☠ ☠ ☠ ☠ --₪₪₪₪₪₪ \\m//
No te he comentado en los
No te he comentado en los demás tutos pero te felicito y se agradece que hagas este tipo de tutoriales de LUA. =)
Re:
Gracias ^ ^
:)
ya era hora, un compendio de tutoriales decentes :)
Aunque viendo el título creo que no hará falta que diga que tb existe xpcall, pq imagino será el segundo :D
Actualmente desarrollando nuestra web y UXCode : http://www.gcrew.es