Crear rutas use idiómáticas
En la Lista 7-11, es posible que te hayas preguntado por qué especificamos use crate::front_of_house::hosting y luego llamamos a hosting::add_to_waitlist en eat_at_restaurant, en lugar de especificar la ruta use hasta la función add_to_waitlist para obtener el mismo resultado, como en la Lista 7-13.
Nombre del archivo: src/lib.rs
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
use crate::front_of_house::hosting::add_to_waitlist;
pub fn eat_at_restaurant() {
add_to_waitlist();
}
Lista 7-13: Traer la función add_to_waitlist al alcance con use, lo cual no es idiómático
Aunque tanto la Lista 7-11 como la Lista 7-13 realizan la misma tarea, la Lista 7-11 es la forma idiómática de traer una función al alcance con use. Traer el módulo padre de la función al alcance con use significa que tenemos que especificar el módulo padre cuando llamamos a la función. Especificar el módulo padre cuando llamamos a la función hace que quede claro que la función no está definida localmente, mientras que minimiza la repetición de la ruta completa. El código de la Lista 7-13 no es claro sobre dónde está definida add_to_waitlist.
Por otro lado, cuando se traen structs, enums y otros elementos con use, es idiómático especificar la ruta completa. La Lista 7-14 muestra la forma idiómática de traer la struct HashMap de la biblioteca estándar al alcance de un crat binario.
Nombre del archivo: src/main.rs
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert(1, 2);
}
Lista 7-14: Traer HashMap al alcance de una forma idiómática
No hay una razón fuerte detrás de este idioma: simplemente es la convención que ha surgido, y la gente se ha acostumbrado a leer y escribir código Rust de esta manera.
La excepción a este idioma es si estamos trayendo dos elementos con el mismo nombre al alcance con declaraciones use, porque Rust no lo permite. La Lista 7-15 muestra cómo traer dos tipos Result al alcance que tienen el mismo nombre pero módulos padres diferentes, y cómo hacer referencia a ellos.
Nombre del archivo: src/lib.rs
use std::fmt;
use std::io;
fn function1() -> fmt::Result {
--snip--
}
fn function2() -> io::Result<()> {
--snip--
}
Lista 7-15: Traer dos tipos con el mismo nombre al mismo alcance requiere usar sus módulos padres.
Como puedes ver, usar los módulos padres distingue los dos tipos Result. Si en cambio especificáramos use std::fmt::Result y use std::io::Result, tendríamos dos tipos Result en el mismo alcance, y Rust no sabría cuál de ellos queremos decir cuando usamos Result.