Leyendo los Valores de los Argumentos
Para permitir que minigrep lea los valores de los argumentos de línea de comandos que le pasamos, necesitaremos la función std::env::args proporcionada en la biblioteca estándar de Rust. Esta función devuelve un iterador de los argumentos de línea de comandos pasados a minigrep. Cubriremos los iteradores en detalle en el Capítulo 13. Por ahora, solo necesitas saber dos detalles sobre los iteradores: los iteradores producen una serie de valores, y podemos llamar al método collect en un iterador para convertirlo en una colección, como un vector, que contiene todos los elementos que produce el iterador.
El código de la Lista 12-1 permite que tu programa minigrep lea cualquier argumento de línea de comandos pasado a él, y luego recopile los valores en un vector.
Nombre del archivo: src/main.rs
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
dbg!(args);
}
Lista 12-1: Recopilando los argumentos de línea de comandos en un vector y mostrándolos
Primero traemos el módulo std::env al ámbito con una declaración use para poder usar su función args. Observe que la función std::env::args está anidada en dos niveles de módulos. Como discutimos en el Capítulo 7, en casos donde la función deseada está anidada en más de un módulo, hemos elegido traer el módulo padre al ámbito en lugar de la función. Al hacerlo, podemos usar fácilmente otras funciones de std::env. También es menos ambiguo que agregar use std::env::args y luego llamar a la función solo con args, porque args podría fácilmente ser confundido con una función que está definida en el módulo actual.
La función args y el Unicode no válido
Tenga en cuenta que std::env::args se interrumpirá si algún argumento contiene Unicode no válido. Si su programa necesita aceptar argumentos que contengan Unicode no válido, use std::env::args_os en su lugar. Esa función devuelve un iterador que produce valores OsString en lugar de valores String. Hemos elegido usar std::env::args aquí por simplicidad porque los valores OsString difieren según la plataforma y son más complejos de trabajar que los valores String.
En la primera línea de main, llamamos a env::args, y inmediatamente usamos collect para convertir el iterador en un vector que contiene todos los valores producidos por el iterador. Podemos usar la función collect para crear muchos tipos de colecciones, por lo que anotamos explícitamente el tipo de args para especificar que queremos un vector de cadenas. Aunque rara vez necesites anotar tipos en Rust, collect es una función que a menudo necesitas anotar porque Rust no puede inferir el tipo de colección que quieres.
Finalmente, imprimimos el vector usando la macro de depuración. Intentemos ejecutar el código primero sin argumentos y luego con dos argumentos:
$ cargo run
--snip--
[src/main.rs:5] args = [
"target/debug/minigrep",
]
$ cargo run -- needle haystack
--snip--
[src/main.rs:5] args = [
"target/debug/minigrep",
"needle",
"haystack",
]
Observe que el primer valor en el vector es "target/debug/minigrep", que es el nombre de nuestro binario. Esto coincide con el comportamiento de la lista de argumentos en C, permitiendo que los programas usen el nombre con el que se invocaron en su ejecución. A menudo es conveniente tener acceso al nombre del programa en caso de que desees imprimirlo en mensajes o cambiar el comportamiento del programa según el alias de línea de comandos que se usó para invocar el programa. Pero con fines de este capítulo, lo ignoraremos y guardaremos solo los dos argumentos que necesitamos.