Secuencias
Un <sequence> declara una columna nombrada de valores, con una longitud de count.
Piénselo como una columna terminada que existe antes de que empiece el renderizado: el
generador llena todas las filas, y en cada fila de salida
se toma un valor por su nombre, ya sea con interpolación
${{Name}} o dentro de una condición if.
Ese es el modelo lógico, y todo lo de esta página se deduce de él. Si la columna
realmente vive en memoria es otra pregunta que el motor responde por usted: el motor por
omisión calcula cada valor a partir de su número de fila mientras la fila pasa, y nunca
guarda la columna, mientras que mode="memory" y la API de objetos sí construyen el
arreglo. Los valores son los mismos en ambos casos — vea
Salidas grandes.
Las secuencias viven en <env>, junto a count y seed. El diseño de una fila (en
<block>) nunca genera valores por sí mismo: solo lee las columnas que sus secuencias ya
produjeron.
Las salidas de ejemplo de abajo son ilustrativas: muestran la forma del resultado y pueden variar entre versiones del núcleo.
- Auna secuencia — una columna, que se llena de manera independiente
- Buna segunda secuencia, que no sabe nada de la primera
- Cuna tercera
- Duna fila: la misma posición tomada de cada columna y ensamblada en una línea de salida
Atributos
| Atributo | Obligatorio | Qué hace |
|---|---|---|
name | sí | El nombre de la secuencia — con él se la referencia, p. ej. ${{City}} |
parent | no | Restringe esta secuencia a un subconjunto de filas. Sintaxis: Parent.Value |
comment | no | Una nota de texto libre; el motor la ignora |
El único hijo obligatorio es una o más etiquetas
<gen>, que producen los valores reales.
Una secuencia simple
Se usa cuando hace falta una sola columna que se pueda referenciar por nombre desde
cualquier parte del diseño. Se declara una vez en <env> y se lee con ${{City}}:
<tdc>
<env count="5" seed="demo">
<sequence name="City">
<gen type="text" value="Guadalajara,Monterrey,Puebla"/>
</sequence>
</env>
<block>
<line><data>${{City}}</data></line>
</block>
</tdc>
Monterrey Guadalajara Puebla Monterrey Puebla
Por omisión los valores se eligen al azar de la lista, y el
seed fija exactamente cuáles le tocan. ¿Quiere el orden estricto de
la lista? Agregue order="sequential" — vea
Máscaras y mayúsculas.
Una secuencia «simple» se define por tener exactamente un <gen> sin nombre. El
acceso es ${{NombreDeLaSecuencia}}.
Con proporciones
La misma forma de una sola columna cubre también las selecciones ponderadas. Dele al
generador text una lista percent y los valores salen en
proporciones exactas:
<sequence name="Gender">
<gen type="text" value="Hombre,Mujer" percent="60,40"/>
</sequence>
Con count=100 esto produce exactamente 60 Hombre y 40 Mujer: percent es un
reparto exacto a lo largo de toda la ejecución, no una probabilidad por fila. Vea
Determinismo y proporciones para saber cómo se hace valer percent.
Hombre 60 Mujer 40
Una secuencia compuesta por valor
Úsela cuando un valor se arma a partir de varios: un nombre completo a partir del
nombre, un espacio y el apellido. Deje los <gen> sin nombre y ponga el texto literal
entre ellos:
<sequence name="FullName">
<gen type="template" value="person.male.firstName"/>
<data> </data>
<gen type="template" value="person.lastName"/>
</sequence>
Robert Williams James Johnson John Smith
${{FullName}} es un solo valor, así que entra tal cual en una ficha, en una columna
CSV o en una de Parquet: no hay nada que unir en la salida.
Los <gen> con y sin nombre conviven en un mismo cuerpo. Los que no llevan nombre
construyen el valor propio de la secuencia; el que sí lo lleva es un campo aparte, se
lee como ${{Name.Field}} y no entra en la concatenación.
Una secuencia compuesta
Se usa cuando una «entidad» tiene varios campos relacionados —nombre, apellido,
edad— que van juntos. Agrúpelos en una sola secuencia en vez de tres separadas, y dele a
cada <gen> un name:
<sequence name="Person">
<gen name="FirstName" type="template" value="person.male.firstName"/>
<gen name="LastName" type="template" value="person.lastName"/>
<gen name="Age" type="number" value="18..60"/>
</sequence>
A los campos se llega con un punto:
<line><data>${{Person.FirstName}} ${{Person.LastName}}, edad ${{Person.Age}}</data></line>
Leandro Zambrano, edad 39 Leandro Juárez, edad 35 Rodolfo Miranda, edad 26
Un campo constante
Un <data> con name es un campo constante y, a diferencia de un generador de
un solo valor, no gasta una tirada:
<sequence name="Row">
<gen name="id" type="increment" value="1"/>
<data name="source">import-2026</data>
</sequence>
${{Row.source}} vale import-2026 en todos los registros.
<gen type="text" value="import-2026"/>Produce el mismo valor y aun así gasta una tirada por fila, así que meterlo en una
configuración ya escrita desplaza todas las columnas declaradas después. Un
<data> con nombre no gasta ninguna, y es la única forma de añadir una constante a
una configuración que alguien ya está usando.
Reglas de las compuestas
- Un
<gen>connamees un campo; sin nombre forma parte del valor propio de la secuencia (ver secuencia compuesta por valor arriba). Un cuerpo con todos los<gen>nombrados es una compuesta por campos y no tiene valor propio. - Los nombres de campo deben ser únicos dentro de la secuencia (error
TDC111si hay un duplicado). - Todos los campos comparten el mismo filtro
parent. Si hay un padre definido, cada campo se llena solo en las filas que coinciden y queda vacío en el resto. - Referenciar una secuencia compuesta sin un campo —
${{Person}}— deja el texto en la salida tal cual. Ese marcador intacto es la pista de que en realidad quería${{Person.FieldName}}.
Campos en condiciones if
El acceso con punto también funciona dentro de las condiciones, no solo en ${{...}}:
<line if="Person.Age >= 18"><data>adulto</data></line>
<line if="Person.Age < 18"><data>menor</data></line>
Una secuencia condicional
Se usa cuando el valor de una columna depende de otra columna. Se enumeran varias
ramas <gen if="…">; gana la primera rama cuya condición sea verdadera. Un <gen>
sin nombre (sin if) actúa como el «si no»:
<sequence name="Age">
<gen type="number" value="0..90"/>
</sequence>
<sequence name="AgeGroup">
<gen if="Age < 18" type="text" value="Menor"/>
<gen if="Age < 65" type="text" value="Adulto"/>
<gen type="text" value="Mayor"/>
</sequence>
Como las ramas se prueban de arriba hacia abajo, Age < 65 solo llega a ver filas que ya
fallaron Age < 18, así que en la práctica significa «18–64». El acceso es por el nombre
de la secuencia, ${{AgeGroup}}:
14 Menor 42 Adulto 71 Mayor 9 Menor 58 Adulto
Una secuencia condicional sigue siendo una sola columna: se lee como ${{AgeGroup}},
igual que una simple. Las varias etiquetas <gen> solo deciden qué valor llena cada
fila.
Secuencias dependientes (parent)
Una secuencia puede depender de otra con parent="Parent.Value". La hija se calcula
solo en las filas donde el padre coincide, y cualquier porcentaje dentro de ella se
mide contra ese subconjunto, no contra el count completo. Este es el corazón del modelo
jerárquico de TDC:
<sequence name="Gender">
<gen type="text" value="Hombre,Mujer" percent="50,50"/>
</sequence>
<sequence name="MaleName" parent="Gender.Hombre">
<gen type="template" value="person.male.firstName"/>
</sequence>
<sequence name="FemaleName" parent="Gender.Mujer">
<gen type="template" value="person.female.firstName"/>
</sequence>
MaleName se materializa solo en las filas donde Gender == Hombre; en las demás queda
vacía. El tratamiento completo —porcentajes anidados, varios niveles— está en
Dependencias jerárquicas.
Una secuencia compuesta con parent
Lo compuesto y parent se combinan directamente. Aquí cada género obtiene su propia
entidad agrupada, y el subconjunto masculino lleva un campo Rank adicional:
<sequence name="Gender">
<gen type="text" value="Hombre,Mujer" percent="50,50"/>
</sequence>
<sequence name="Male" parent="Gender.Hombre">
<gen name="FirstName" type="template" value="person.male.firstName"/>
<gen name="LastName" type="template" value="person.lastName"/>
<gen name="Rank" type="text" value="Soldado,Capitán" percent="70,30"/>
</sequence>
<sequence name="Female" parent="Gender.Mujer">
<gen name="FirstName" type="template" value="person.female.firstName"/>
<gen name="LastName" type="template" value="person.lastName"/>
</sequence>
<block>
<line if="Gender == Hombre"><data>H: ${{Male.FirstName}} ${{Male.LastName}} (${{Male.Rank}})</data></line>
<line if="Gender == Mujer"><data>M: ${{Female.FirstName}} ${{Female.LastName}}</data></line>
</block>
M: Justina Cifuentes H: Bonifacio Ordóñez (Soldado) M: Silvia Guerra M: Azucena Mesa H: Faustino Posada (Capitán) H: Justo Uribe (Soldado)
Lo que esto garantiza:
- Los tres campos
Male.*se materializan solo en las filas masculinas; en las femeninas quedan vacíos (y viceversa). Male.Rankse reparte70% Soldado, 30% Capitándentro del subconjunto masculino: los porcentajes se cuentan contra el número de hombres, no contra elcounttotal.
Determinismo y orden de los campos
Los campos de una secuencia compuesta se materializan en orden de declaración, y cada
<gen> consume el PRNG de forma independiente. Eso tiene una
consecuencia que vale la pena recordar:
Intercambiar dos etiquetas <gen name="…"> cambia la salida con la misma semilla. El
primer campo drena una porción distinta del flujo aleatorio que antes, así que todos los
campos que vienen después se desplazan.
<!-- Estos dos producen valores DIFERENTES con el mismo seed -->
<sequence name="Person">
<gen name="FirstName" type="template" value="person.male.firstName"/>
<gen name="Age" type="number" value="18..60"/>
</sequence>
<sequence name="Person">
<gen name="Age" type="number" value="18..60"/>
<gen name="FirstName" type="template" value="person.male.firstName"/>
</sequence>
Si necesita una salida reproducible byte por byte entre ejecuciones, fije el orden de los campos una vez y no reordene los generadores después de haberse comprometido con una semilla. Hay más sobre lo que la semilla sí garantiza y lo que no en Determinismo y proporciones.
Fuentes de valores relacionadas
Otras dos fuentes nombradas viven junto a <sequence> en <env> y también se leen con
${{Name}}:
<mix>— una distribución por porcentaje exacto, donde cada rama puede ser un compuesto completo de literales y generadores (no solo un valor suelto).<switch>— una tabla de búsqueda determinista de clave → valor.
Cuando solo necesita una columna de valores aleatorios o ponderados, la herramienta es
<sequence>.
Siguiente
- Generadores — el
<gen>que produce los valores de una secuencia. - Determinismo y proporciones — cómo encajan
seed,countypercent. - Dependencias jerárquicas — el modelo
completo de
parent.