Tablas y Registros
Las tablas en BLOX son una de las estructuras más potentes y flexibles del lenguaje.
Permiten representar colecciones de registros, donde cada registro agrupa pares campo = valor.
Una tabla puede usarse para:
- almacenar datos tipo lista
- representar filas de una planilla
- trabajar con registros heterogéneos
- importar y exportar datos
- buscar, filtrar, mezclar y transformar información
¿Qué es una tabla en BLOX?
Una tabla es un conjunto ordenado de registros.
Cada registro contiene campos con nombre, por ejemplo:
nombreedadciudad
y cada campo puede guardar distintos tipos de dato:
NUMERICOSTRINGLOGICOVECTORMATRIZTABLA
TABLA personas
personas = { nombre = "Ana", edad = 28, ciudad = "Asuncion" }
personas = { nombre = "Luis", edad = 35, ciudad = "Encarnacion" }
En este ejemplo:
personases una tablapersonas[1]es el primer registropersonas[2]es el segundo registro
Tip: Las tablas se expanden automáticamente a medida que agregas registros. No necesitas definir previamente la cantidad de filas ni los nombres de los campos.
¿Qué es un registro?
Un registro es una sola fila lógica dentro de una tabla.
TABLA personas
personas = {
nombre = "Carlos",
edad = 30,
ciudad = "Asuncion"
}
Aquí, personas[1] es un registro con tres campos:
nombreedadciudad
Puedes imprimirlo directamente:
IMPRIMIR(personas[1])
Crear tablas
Crear una tabla vacía
TABLA personas
Agregar registros
TABLA personas
personas = { nombre = "Ana", edad = 28 }
personas = { nombre = "Luis", edad = 35 }
personas = { nombre = "Marta", edad = 22 }
Cada asignación de este tipo agrega un nuevo registro al final de la tabla.
Acceso a registros y campos
Acceso por índice
registro = personas[1]
Acceso por nombre de campo
nombre = personas[1].nombre
edad = personas[1].edad
Acceso con corchetes
nombre = personas[1]["nombre"]
edad = personas[1]["edad"]
Acceso dinámico a campos
Esto es útil cuando el nombre del campo está en una variable:
STRING campo, valor
campo = "nombre"
valor = personas[1][campo]
Modificar valores
Puedes modificar un campo existente de esta forma:
personas[2].ciudad = "Ciudad del Este"
o con clave dinámica:
STRING campo
campo = "ciudad"
personas[2][campo] = "Ciudad del Este"
Regla importante: creación automática de campos
En BLOX, una asignación como:
tabla[i][campo] = valor
tabla[i].campo = valor
tiene esta semántica:
- si el campo ya existe, se modifica
- si el campo no existe, se crea automáticamente y luego se asigna el valor
Ejemplo:
TABLA personas
personas = { nombre = "Roberto", ciudad = "Concepcion" }
personas[1].email = "rob@mail.com"
Resultado:
{
nombre = "Roberto",
ciudad = "Concepcion",
email = "rob@mail.com"
}
Nota importante: Este comportamiento es parte aceptada del lenguaje. No se considera un error.
Modo estricto con ES_CAMPO()
Si no quieres que un campo se cree automáticamente, puedes proteger la asignación con ES_CAMPO().
SI (ES_CAMPO(personas[1], "edad")) ENTONCES
personas[1].edad = 23
SINO
ERROR("Campo inexistente.")
FIN_SI
Esto es útil cuando quieres distinguir entre:
- modificar un campo existente
- crear accidentalmente un campo nuevo por error tipográfico
Tablas heterogéneas
En BLOX, no todos los registros tienen que tener los mismos campos.
TABLA personas
personas = { nombre = "Carlos", edad = 30, ciudad = "Asuncion" }
personas = { nombre = "Juan", edad = 21, ciudad = "Encarnacion" }
personas = { nombre = "Roberto", ciudad = "Concepcion", email = "rob@mail.com" }
Aquí:
- los registros 1 y 2 tienen
edad - el registro 3 no tiene
edad - el registro 3 tiene
email - los demás no tienen
email
Por eso, en tablas heterogéneas conviene usar:
ES_CAMPO(reg, campo)CLAVES(reg)CLAVES_INFO(reg)TIPO_DATO(tabla, campo)
Subtablas
Un campo también puede contener otra tabla.
TABLA personas
personas = {
nombre = "Juan",
direccion = {
ciudad = "Encarnacion",
barrio = "Centro"
}
}
Acceso a subcampos
ciudad = personas[1].direccion.ciudad
o también:
ciudad = personas[1]["direccion"]["ciudad"]
Modificar subcampos
personas[1].direccion.barrio = "San Roque"
Propiedades y métodos frecuentes
.dim — cantidad de registros
NUMERICO cantidad
cantidad = personas.dim
.CLAVES() — nombres de campos de un registro
STRING campos[10]
campos = personas[1].CLAVES()
CLAVES(registro)
STRING campos[10]
campos = CLAVES(personas[1])
CLAVES_INFO(registro)
Devuelve una tabla con información más completa sobre los campos del registro:
- nombre
- tipo
- si es subtabla
- nivel
TABLA info
info = CLAVES_INFO(personas[1])
IMPRIMIR(info[1])
ES_CAMPO(registro, campo)
Verifica si un campo existe en ese registro.
SI (ES_CAMPO(personas[1], "email")) ENTONCES
IMPRIMIR(personas[1].email)
FIN_SI
TIPO_DATO(tabla, campo)
Obtiene el tipo de dato asociado a un campo.
STRING tipo
tipo = TIPO_DATO(personas, "edad")
IMPRIMIR(tipo)
Valores típicos:
NUMERICOSTRINGLOGICOTABLANO_EXISTEDESCONOCIDO
Operaciones frecuentes con tablas
Agregar un registro
AGREGAR(personas, { nombre = "Santiago", edad = 33 })
Agregar un campo a toda la tabla
AGREGAR(personas, "email")
Agregar un campo a un solo registro
AGREGAR(personas[2], "telefono")
personas[2].telefono = "555-123"
Eliminar un campo de un registro
ELIMINAR(personas[2], "telefono")
Eliminar un registro
ELIMINAR(personas[2])
Eliminar un registro por índice
ELIMINAR(personas, 2)
Vaciar una tabla
ELIMINAR(personas)
Ejemplo completo
TABLA personas
STRING campo
personas = {
nombre = "Carlos",
edad = 30,
ciudad = "Asuncion"
}
personas = {
nombre = "Roberto",
ciudad = "Concepcion"
}
campo = "email"
personas[2][campo] = "rob@mail.com"
IMPRIMIR(personas[1])
IMPRIMIR(personas[2])
Salida esperada:
{
nombre = "Carlos",
edad = 30,
ciudad = "Asuncion"
}
{
nombre = "Roberto",
ciudad = "Concepcion",
email = "rob@mail.com"
}
Buenas prácticas
- Usa
ES_CAMPO()cuando quieras evitar la creación automática de campos. - Usa
CLAVES()oCLAVES_INFO()para explorar registros heterogéneos. - Usa
TIPO_DATO()cuando una función de tabla deba soportar varios tipos. - Si trabajas con subtablas, valida primero su existencia antes de acceder a campos internos.
- Si vas a exportar a CSV o JSON, recuerda que no todos los registros tienen por qué compartir exactamente los mismos campos.
Errores frecuentes
1. Confundir edad con Edad
Los nombres de campo son sensibles al texto exacto.
personas[1].edad = 21
personas[1].Edad = 23
Eso crea dos campos distintos:
edadEdad
2. Asumir que todos los registros tienen todos los campos
Esto puede fallar en tablas heterogéneas:
IMPRIMIR(personas[3].edad)
Si no estás seguro, protege con:
SI (ES_CAMPO(personas[3], "edad")) ENTONCES
IMPRIMIR(personas[3].edad)
FIN_SI
3. Confundir la tabla completa con un registro
personases la tabla completapersonas[1]es un registropersonas[1].nombrees un campo del registro
Relación con JSON
Las tablas BLOX se parecen mucho a estructuras tipo JSON.
Por eso existen funciones como:
JSON_A_TABLA()TABLA_A_JSON()TABLA_A_STRING()STRING_A_TABLA()
Estas funciones permiten convertir entre texto estructurado y tablas BLOX de forma muy natural.
Persistencia con SQLite
Una TABLA no solo sirve para trabajar con datos en memoria.
Tambien puede volverse persistente usando SQLite.
Las dos funciones clave son:
sqlite.importar(db, "tabla_destino", tabla)tabla = sqlite.exportar(db, "SELECT ...")
Con esto puedes:
- guardar una tabla entre ejecuciones
- recuperar sus registros mas adelante
- consultar los datos con SQL
- combinar BLOX y SQLite en un mismo flujo de trabajo
Ejemplo conceptual:
INCLUIR "sqlite.api"
SQLITE db
TABLA personas, out
personas = { nombre = "Ana", edad = 28 }
personas = { nombre = "Luis", edad = 35 }
db = sqlite.abrir("personas.db")
sqlite.importar(db, "personas", personas)
out = sqlite.exportar(db, "SELECT nombre, edad FROM personas ORDER BY nombre;")
sqlite.cerrar(db)
Para una explicacion completa del tipo SQLITE y de la API de base de datos, consulta el documento Bases de Datos.