6 Tipos de datos compuestos
En la Sección 5.2 ya hemos visto los tipos básicos de datos: reales, enteros, caracteres, booleanos y unitario. Sin embargo, con frecuencia necesitaremos agrupar varios valores para representar una entidad o manejar colecciones de datos. Para ello, Rust define dos tipos de datos compuestos: las tuplas y los arrays.
6.1 Tuplas
Una tupla es una colección ordenada de valores. Sus elementos pueden tener tipos distintos y su longitud no puede cambiar una vez definida. Se escriben entre paréntesis, separados por comas.
fn main() {
let persona = ("Ana", 25, true);
println!("Contenido de la tupla:");
println!("\t{:?}", persona);
println!("Elementos de la tupla:");
println!("\tNombre: {}", persona.0);
println!("\tEdad: {}", persona.1);
println!("\tActivo: {}", persona.2);
}La variable
personacontiene una tupla con tres elementos: una cadena ("Ana"), un entero (25) y un booleano (true).La sentencia
println!("\t{:?}", persona);muestra el contenido completo de la tupla. El especificador
:?indica que el valor debe imprimirse usando su representación de depuración (debug).Los elementos de una tupla se acceden mediante un punto seguido de su posición. El primer elemento es
persona.0, el segundopersona.1y el terceropersona.2.La posición ha de ser un literal numérico (un número tal cual). No puede ser una variable ni una expresión. El índice identifica un campo concreto y debe conocerse en compilación
Las últimas sentencias muestran cada elemento por separado:
println!("\tNombre: {}", persona.0); println!("\tEdad: {}", persona.1); println!("\tActivo: {}", persona.2);El especificador
{}indica dónde debe insertarse el valor que aparece como segundo argumento deprintln!.La secuencia
\trepresenta un carácter de tabulación y se utiliza aquí para mejorar la presentación de la salida.
6.2 La tupla vacía
La tupla vacía se escribe () y no contiene ningún elemento. Como vimos en la Sección 5.2.2 también se le llama valor unitario y es de tipo unitario.
fn main() {
let tupla_vacia = ();
println!("{:?}", tupla_vacia);
}Aunque pueda parecer poco útil, la tupla vacía tiene un papel importante en Rust. Por ejemplo, es el valor que devuelven muchas funciones cuya finalidad es realizar una acción y no producir un resultado.
6.3 Arrays
Al igual que una tupla, un array es una colección ordenada de valores cuya longitud no puede cambiar una vez definido. Pero a diferencia de las tuplas, sus elementos han de ser todos del mismo tipo.
Los elementos de un array se escriben entre corchetes, separados por comas. También se usan los corchetes para acceder a los elementos por su índice. Al igual que en C y muchos otros lenguajes, el primer elemento es el 0, el segundo es el 1, etc. El índice puede ser un literal numérico, una variable o una expresión.
fn main() {
let numeros = [10, 20, 30, 40, 50];
println!("Contenido del array:");
println!("\t{:?}", numeros);
println!("Elementos del array:");
println!("\tPrimero: {}", numeros[0]);
println!("\tSegundo: {}", numeros[1]);
println!("\tTercero: {}", numeros[2]);
}
La variable numeros contiene un array con cinco elementos. Todos ellos son enteros. Si alguno no lo fuera, el compilador mostraría un error. Como en el siguiente ejemplo:
fn main() {
let datos = [10, 20, "azul"]; // ¡ERROR! Los tipos han de ser iguales.
println!("Contenido del array:");
println!("\t{:?}", datos);
}También es posible definir un array indicando su tamaño y el valor que tendrán todos sus elementos. Para ello se escribe el valor inicial, seguido de un punto y coma y del número de elementos:
let ceros = [0; 5];Esto significa que se debe repetir el valor 0 cinco veces. El array ceros contiene cinco elementos, todos ellos iguales a 0. El tipo de los elementos es i32, que es el tipo que Rust deduce para el literal 0. Esta forma de definir arrays resulta especialmente útil cuando todos sus elementos han de comenzar con el mismo valor. Por ejemplo:
fn main() {
let ceros = [0; 5];
println!("Contenido del array:");
println!("\t{:?}", ceros);
}También se puede indicar explícitamente el tipo de los elementos:
let valores: [f64; 4] = [0.0; 4];Aquí valores es un array de cuatro elementos de tipo f64, todos ellos inicializados a 0.0.
La forma [valor; tamaño] requiere que el valor pueda copiarse para inicializar los elementos. En este capítulo trabajaremos con tipos sencillos, como i32, f64 o bool, que cumplen este requisito. En la Sección 9.5 veremos que no todos los tipos de Rust implementan el trait Copy. Con algunos de ellos no será posible utilizar esta forma de inicialización, aunque sí se podrán definir arrays escribiendo sus elementos uno a uno.
En cualquier caso, el tamaño siempre forma parte del tipo del array. Por tanto, [i32; 5] y [i32; 10] son tipos distintos, aunque sus elementos sean del mismo tipo.
6.4 Comparación entre tuplas y arrays
La Tabla 6.1 resume las similitudes y diferencias entre tuplas y arrays.
| Característica | Tupla | Array |
|---|---|---|
| Longitud fija | Sí | Sí |
| Elementos del mismo tipo | No necesariamente | Sí |
| Delimitadores | Paréntesis () |
Corchetes [] |
| Acceso a elementos | Punto (.0, .1, …) |
Índice ([0], [1], …) |
| Acceso mediante vble o expr. | No | Sí |
| Ejemplo | ("TCP", 443, true) |
[10, 20, 30, 40, 50] |
6.5 Resumen
En este capítulo hemos presentado los dos tipos de datos compuestos básicos que proporciona Rust: las tuplas y los arrays.
Las ideas principales son las siguientes:
- Una tupla agrupa un número fijo de valores que pueden ser de tipos diferentes.
- Los elementos de una tupla se acceden mediante su posición, utilizando la notación
.0,.1,.2, etc. - La tupla vacía
()representa el valor unitario y suele utilizarse como valor de retorno de funciones que realizan una acción pero no producen un resultado. - Un array almacena un número fijo de elementos del mismo tipo.
- Los elementos de un array se acceden mediante un índice entre corchetes, comenzando por el índice
0. - Tanto las tuplas como los arrays tienen un tamaño fijo, pero las tuplas permiten mezclar tipos mientras que los arrays no.
- En los arrays se pueden usar variables o expresiones para los índices. En las tuplas, no. Solo constantes numéricas literales.
En los próximos capítulos estudiaremos nuevos tipos de datos que permiten representar estructuras más complejas y colecciones de tamaño variable.