En Rust, un slice es una referencia a una parte de una colección, como un arreglo o un vector. Un slice no posee los datos, simplemente apunta a una secuencia continua de elementos dentro de una colección. Los slices son útiles para trabajar con subsegmentos de colecciones sin la necesidad de copiar los datos.
&[T]
): Te permiten leer pero no modificar los datos.
&mut [T]
): Permiten tanto leer como modificar los datos.
Los slices se crean a partir de colecciones como arreglos o vectores usando la notación de rangos ([inicio..fin]
). Aquí tienes un ejemplo básico:
fn main() {
let arreglo = [1, 2, 3, 4, 5];
let slice = &arreglo[1..4]; // Slice desde el índice 1 al 3 (excluyendo el 4)
println!("Slice: {:?}", slice); // Output: [2, 3, 4]
}
En este ejemplo:
&arreglo[1..4]
crea un slice inmutable que toma los elementos desde el índice 1 hasta el índice 3.
Puedes modificar los elementos de una colección usando un slice mutable. A continuación se muestra cómo hacerlo:
fn main() {
let mut arreglo = [1, 2, 3, 4, 5];
let slice_mut = &mut arreglo[1..4]; // Slice mutable
slice_mut[0] = 10; // Modifica el primer elemento del slice (índice 1 del arreglo original)
println!("Arreglo modificado: {:?}", arreglo); // Output: [1, 10, 3, 4, 5]
}
En este caso, el slice mutable &mut arreglo[1..4]
te permite modificar los valores de los elementos subyacentes en el arreglo original.
Puedes acceder a los elementos dentro de un slice utilizando el índice, de la misma manera que lo harías con un arreglo o vector:
fn main() {
let arreglo = [10, 20, 30, 40, 50];
let slice = &arreglo[1..4]; // Slice: [20, 30, 40]
println!("Primer elemento del slice: {}", slice[0]); // Output: 20
println!("Segundo elemento del slice: {}", slice[1]); // Output: 30
}
Puedes obtener la longitud de un slice con el método .len()
:
fn main() {
let arreglo = [1, 2, 3, 4, 5];
let slice = &arreglo[1..4];
println!("Longitud del slice: {}", slice.len()); // Output: 3
}
El slice tiene una longitud de 3, ya que incluye tres elementos del arreglo original.
Puedes iterar sobre un slice usando un bucle for
o métodos iteradores. Aquí te mostramos cómo hacerlo:
fn main() {
let arreglo = [10, 20, 30, 40, 50];
let slice = &arreglo[1..4]; // Slice: [20, 30, 40]
for elemento in slice.iter() {
println!("Elemento: {}", elemento);
}
}
Esto imprime cada elemento del slice (20
, 30
, 40
).
Los slices también funcionan con vectores, ya que los vectores son colecciones dinámicas en Rust. La creación y manipulación de slices es similar a la de los arreglos:
fn main() {
let vector = vec![100, 200, 300, 400, 500];
let slice = &vector[2..4]; // Slice desde el índice 2 al 3
println!("Slice del vector: {:?}", slice); // Output: [300, 400]
}
En Rust, un slice es lo que se llama un fat pointer (puntero gordo). Esto significa que un slice no solo apunta al primer elemento de la secuencia, sino que también almacena la longitud del slice. Esto permite a Rust manejar la memoria de manera eficiente y segura sin causar acceso fuera de los límites.
Este ejemplo combina todo lo aprendido, creando y manipulando un slice inmutable y mutable de un arreglo:
fn main() {
let mut arreglo = [10, 20, 30, 40, 50];
// Crear slice inmutable
let slice_inmutable = &arreglo[1..4];
println!("Slice inmutable: {:?}", slice_inmutable);
// Crear slice mutable y modificar los valores
let slice_mutable = &mut arreglo[2..5];
slice_mutable[0] = 300;
slice_mutable[1] = 400;
println!("Slice mutable modificado: {:?}", slice_mutable);
println!("Arreglo completo modificado: {:?}", arreglo);
}
El tipo slice en Rust es una herramienta esencial para trabajar con partes de colecciones de datos como arreglos o vectores de manera eficiente y sin copiar los datos. Los slices permiten tanto la lectura (inmutable) como la modificación (mutable) de subsegmentos de colecciones. Entender cómo funcionan los slices y sus reglas de seguridad te ayudará a aprovechar al máximo la gestión de memoria segura de Rust.
Para más detalles, consulta la documentación oficial de Rust.
Jorge García
Fullstack developer