Bienvenidos sean a este post, una particularidad de este lenguaje es que hace administracion automatica de memoria, en realidad hoy en dia todos los lenguajes lo hacen pero los mas viejos no, y esto implica que el programa crea objetos (tablas, funciones, etc) pero no existe una funcion para borrar dichos objetos porque Lua borra automaticamente objetos que se convierten en basura usando la coleccion de basura.

Anuncios

Esto te libera de la mayor parte de la carga de administracion de memoria y mas importante aun es que te libera de los errores relacionados a esta actividad, tales como punteros colgantes y fugas de memoria, a diferencia de otros coleccionistas el coleccionista de basura de Lua no tiene problemas con los ciclos, no tiene necesidad de ninguna accion especial cuando usa estructuras de datos ciclicos, ellos son recolectados como cualquier otro dato, sin embargo algunos coleccionistas necesitan de tu ayuda por mas independientes e inteligentes que sean.

Anuncios

Un coleccionista de basura solo puede recolectar lo que realmente es basura, el no puede adivinar que consideras basura, un ejemplo tipico es la pila (stack), implementado con un array y un indice a la parte superior, sabemos que la parte valida de un array solo va hacia la parte superior pero Lua no, si haces estallar (pop) un elemento simplemente decrementando la parte superior lo que el objeto deja en el array no es basura para Lua incluso si tu programa no lo vuelve usar, en ambos casos es tu responsabilidad (en realidad de tu programa) asignar nil a estas posiciones asi estas no bloquean un objeto libre, sin embargo limpiar solamente las referencias puede que no sea suficiente, algunas construcciones necesitan una colaboracion extra entre el programa y el coleccionista, un ejemplo tipico ocurre cuando queres mantener una coleccion de todos los objetos activos de algun tipo (p.e. archivos) en tu programa, la tarea se ve simple: todo lo que debes hacer es insertar cada objeto nuevo dentro de la coleccion.

Anuncios

Sin embargo, una vez que el objeto esta dentro de la coleccion nunca sera coleccionado incluso si ninguno mas lo apunta, la coleccion lo hace pero Lua sabe que esta referencia no deberia prevenir el reclamo de dicho objeto, al menos que le digas a Lua sobre esta hecho.

Anuncios

Las tablas debiles (Weak Tables) son el mecanismo que usas para decirle a Lua que una referencia no debe prevenir el reclamo de un objeto, una referencia debil es una referencia, perdon por la redundancia, a un objeto que no es considerada por el coleccionista de basura y si todas las referencias que apuntan a un objeto son debiles el objeto es recolectado y de alguna forma estas referencias debiles son borradas, esto significa que si un objeto es retenido solamente dentro de tablas debiles Lua eventualmente coleccionara este objeto.

Anuncios

Las tablas tienen claves y valores y ambas pueden contener cualquier tipo de objeto, bajo circunstancias normales el coleccionista de basura no colecciona objetos que aparecen como claves o como valores de una tabla accesible, por lo tanto claves y valores son referencias fuertes porque previenen los reclamos de un objetos a los que refieren, en una tabla debil donde tanto las claves como los valores son debiles, esto implica que tenemos tres tipos de tablas debiles

  • tablas con claves debiles
  • tablas con valores debiles
  • tablas debiles completas, donde ambos son debiles

Sin importar el tipo de tabla cuando una clave o un valor es colectado hace desaparecer a la entrada completa de la tabla.

Anuncios

La debilidad de la tabla es dado por el campo __mode de su metatabla, el valor de este campo, cuando existe, deberia ser una cadena, si esta cadena contiene la letra ‘k’ significa que las claves en la tabla son debiles, si la cadena contiene la letra ‘v’ significa que los valores en la tabla son debiles, el siguiente ejemplo ilustra la conducta basica de la tablas debiles:

a = {}
b = {__mode = "k"}
setmetatable(a, b)		-- 'a' tiene claves debiles
clave = {}			-- crea la primera clave
a[clave] = 1
clave = {}			-- crea ña segunda clave
a[clave] = 2
collectgarbage()		-- fuerza un ciclo colector de basura
for k, v in ipairs(a= do print(v) end   -- Devuelve 2
Anuncios

En este caso la segunda asignacion clave = {} sobreescribe la primera clave, cuando el colector corre, como no hay otra referencia a la primera clase, esta es coleccionada y la entrada correspondiente en la tabla es removida, la segunda clave todavia esta anclada en la variable clave asi que no es coleccionada, observemos que solamente los objetos pueden ser coleccionados de una tabla debil, valores como numeros y booleanos no son coleccionables, por ejemplo si insertamos una clave numerica en un tabla a (de nuestro ejemplo previo), nunca sera removida por el coleccionista pero si el valor corresponde a una clave numerica es coleccionada, luego la entrada completa es removida de la tabla debil.

Anuncios

Las cadenas presentan una sutileza aqui porque a pesar de que las cadenas son coleccionables desde un punto de vista de implementacion, ellas no son como los otros objetos coleccionables, otros objetos como las tablas y las funciones son creadas explicitamente, por ejemplo cuando Lua evalua la expresion {} este crea una nueva tabla y cuando evalua a function() … end este crea una nueva funcion (en realidad es un cierre) pero Lua crea una nueva cadena cuando evalua “a” .. “b”? Que pasa si ya existe una cadena “ab” en nuestro sistema? Lua crea uno nuevo? Puede el compilador crear una nueva cadena antes de correr el programa?, en realidad esto no importa porque estos son detalles de implementacion.

Anuncios

Desde el punto de vista del programador las cadenas son valores, no objetos, por lo tanto como un numero o un booleano una cadena no es removida de una tabla debil, al menos que su valor asociado sea coleccionado.

Anuncios

En resumen, hoy hemos visto tablas debiles, que son, para que sirven, como se implementan y cual es su verdadera funcion, espero les haya sido util sigueme en Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Tengo un Patreon donde podes acceder de manera exclusiva a material para este blog antes de ser publicado, sigue los pasos del link para saber como.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00