Encadenando Métodos

Rust es un lenguaje de programación de sistemas como C y C++ y su código se puede escribir mediante órdenes (comandos) separados en líneas separadas, pero también es un lenguaje que permite un estilo de programación funcional. Ambos estilos de programación son correctos, pero el estilo funcional suele ser más sintético. Produce código más conciso y breve. A continuación se muestra un ejemplo del estilo no funcional (denominado estilo imperativo) en el que se construye un Vec que contiene números de 1 a 10:

fn main() {
    let mut new_vec = Vec::new();
    let mut counter = 1;

    while counter < 11 {
        new_vec.push(counter);
        counter += 1;
    }

    println!("{:?}", new_vec);
}

Esto imprime [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].

A continuación, se muestra cómo se codificaría mediante un estilo funcional:

fn main() {
    let new_vec = (1..=10).collect::<Vec<i32>>();
    // También se podría haber escrito así
    // let new_vec: Vec<i32> = (1..=10).collect();
    println!("{:?}", new_vec);
}

.collect() crea colecciones de muchos tipos posibles, por eso hay que indicar el tipo.

Con el estilo funcional de programación se pueden encadenar métodos. Encadenar métodos significa que se pueden unir para formar una única sentencia. A continuación se muestra un ejemplo de muchos métodos unidos:

fn main() {
    let my_vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    let new_vec = my_vec.into_iter().skip(3).take(4).collect::<Vec<i32>>();

    println!("{:?}", new_vec);
}

El ejemplo anterior crea un Vec que contiene [3, 4, 5, 6]. La sentencia contiene mucha información en una sola línea. Si se separan en diferentes líneas para hacerlo más fácil de leer (y se añaden comentarios explicativos):

fn main() {
    let my_vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    let new_vec = my_vec
        .into_iter() // Itera a través de todos los elementos.
                     // Esta función devuelve los elementos, no referencias a ellos.
        .skip(3) // se salta tres elementos, en este caso: 0, 1 y 2
        .take(4) // obtiene los cuatro primeros que quedan: 3, 4, 5 y 6
        .collect::<Vec<i32>>(); // los coloca en un nuevo Vec<i32>

    println!("{:?}", new_vec);
}

Se puede utilizar este estilo funcional de forma amplia cuando se estudien los closures (cierres) y los iteradores. Por ello, estos conceptos se ven a continuación.