Una de las cosas que ha sido criticada por los novatos en Rust es el mecanismo de inclusión de archivos. Hace aproximadamente 2 días, dediqué alrededor de 5 horas a cómo se suponía que debía incluir un archivo al que se hacía referencia en el fondo de un árbol de directorios. Los documentos no ayudaron, ya que eran estructuras simples. Aquí le mostraré cómo puede incluir su código en diferentes partes de la aplicación, incluso cuando la estructura es compleja, y le ahorrará horas en cómo hacer esta tarea supuestamente trivial.
Me referiré a rasgos, módulos, enumeraciones, funciones, estructuras como "recursos" en general.
También me gustaría compartir con ustedes un video de TensorProgramming "Rust 2018 - Módulos, cajas externas, submódulos, rutas y modificadores de visibilidad" de TensorProgramming - https://www.youtube.com/watch?v=U8uhW9bFm-8 ya que este fue el recurso que me enseñó cómo incluir correctamente los recursos.
Puede encontrar un repositorio de ejemplo aquí: https://github.com/superjose/rust-include-files-example
No existe tal cosa como un "archivo" cuando hace referencia a su recurso.
Rust no ve los archivos como archivos, pero los ve como módulos y los archivos dentro de las carpetas como submódulos. Por lo tanto, no puede simplemente hacer referencia a ellos directamente con una importación simple o un espacio de nombres perforado al estilo de JavaScript o C# y usarlos de inmediato.
Necesitas crear un árbol de
pub mod file_name
(Llamados barriles en el mundo JS) que exponen estos módulos a los externos y (consulte los puntos a continuación) les permiten ser descubiertos y consumidos.Cómo incluir un módulo (archivo)
Supongamos que tenemos la siguiente estructura (puede obtener esto del repositorio ).
Y le gustaría incluir varias funciones de módulos dispersos dentro del
/src/house
directorio en nuestro main.rs
expediente: mod house; // Please, do not use hyphens as this is proven to have an // inconsistent behavior. // https://github.com/rust-lang/book/issues/1709 // https://rust-lang.github.io/rfcs/0940-hyphens-considered-harmful.html // https://stackoverflow.com/a/57535534/1057052 #[path = "./welcome-home.rs" ] mod welcome_home; // Includes the function directly // When using crate, you use the root directory to include everything. use crate::house::diner; use house::bathroom::sink::wash_face; use house::kitchen::prepare::food_preparation::prepare_food; fn main () { let user = "Jose" ; building::lobby::arrive_lobby(); welcome_home::run(user); house::bathroom::shower::take_shower(house::bathroom::shower::ShowerTemperature::Cold); wash_face(); house::bathroom::toilet::use_toilet(); prepare_food(); diner::eat(); } // https://doc.rust-lang.org/reference/visibility-and-privacy.html /** * From the docs (Link above) * * By default, everything in Rust is private, with two exceptions: * Associated items in a pub Trait are public by default; Enum * variants in a pub enum are also public by default. When an * item is declared as pub, it can be thought of as being accessible * to the outside world. */ mod building { pub mod lobby { pub ( in crate ) fn arrive_lobby () { println! ( "You have arrived to the lobby" ); } } }
- Para incluir un archivo junto al archivo main.rs, simplemente especifique
mod
welcome_home
welcome-home.rs
welcome_home::run()
- Para usar un mod que existe dentro del archivo, simplemente puede escribir su nombre como espacio de nombres y profundizar hasta el recurso que está buscando. Comprenda que si el módulo no es público, no podrá acceder a él dentro de su archivo. Consulte la referencia de visibilidad y privacidad de Rust para obtener más información. Si desea incluir el
arrive_lobby
building::lobby::arrive_lobby
- Puede usar un recurso directamente especificándolo con el
use
house::bathroom:sink::wash_face()
wash_face()
- En caso de
wash_face
house::bathroom::sink::wash_face
pub mod bathroom
bathroom.rs
/src/house/bathroom.rs
/src/house/bathroom
pub mod sink; pub mod shower; pub mod toilet;
pub
use house::bathroom::sink::wash_face
- Después
use
crate
- Si hace referencia a un recurso a través de un mod y ese recurso está profundamente anidado, solo especifica el primer nivel del módulo y luego lo desglosa. Por ejemplo: en caso de
house::bathroom::shower::take_shower(house::bathroom::shower::ShowerTemperature::Cold)
mod house
Incluir archivos o módulos de otra carpeta, directorio o submódulo
Esta es quizás la forma más complicada y antinatural para que todas las personas nuevas en Rust hagan referencia a módulos en otros archivos. los
wash_face
función es un ejemplo de una función profundamente anidada. Os animo a ver el repositorio para entender mejor cómo funciona todo.Rust sigue una convención: debe crear un archivo con el nombre del directorio al que desea acceder y colocarlo junto al directorio al que desea acceder.
Luego, deberá exponer cada uno de los archivos dentro del directorio que desea que el compilador haga accesible:
Ejemplo:
Me gustaría acceder a los contenidos de
shower.rs
, sink.rs
, y toilet.rs
dentro de /src/house/bathroom
carpeta. Primero, tendría que crear un
/src/house/bathroom.rs
archivo que haría visible o barril shower.rs,
sink.rs
y toilet.rs
archivos Dentro especificaría el nombre de cada uno de los archivos como módulos públicos: // Contents of /src/house/bathroom.rs pub mod shower; pub mod sink; pub mod toilet;
Entonces, necesitaría exponer esto
bathroom.rs
archivo de la /src/house
directorio. Para eso, necesitaría crear un /src/house.rs
archivo, que exportaría el bathroom.rs
archivo que acabo de definir ahora. // Contents of /src/house/mod.rs or /src/house.rs pub mod bathroom; pub mod diner; pub mod kitchen;
Como puedes ver
pub mod bathroom
hace bathroom.rs
archivo visible. Tenga en cuenta la convención: pub mod file_name_without_rs_extension
Debe hacer esto cada vez que desee que un módulo (archivo) sea visible para el módulo externo (directorio/carpeta).
Nota : vería en el repositorio y en la imagen de arriba que hay
mod.rs
archivos; En versiones anteriores a Rust 2018, la única forma de que Rust descubriera estos directorios era que especificaran mod.rs
dentro del directorio.Esto se volvió problemático porque si quería especificar un archivo con el mismo nombre del directorio, el compilador se confundiría. Es por eso que a partir de Rust 2018 (Busque la línea que dice
edition = "2018"
en tus cargo.toml
expediente).En este ejemplo
/src/house/mod.rs
es lo mismo que /src/house.rs
Puede crear cualquiera de esos archivos y funcionaría.Incluyendo otros módulos hermanos (archivos) dentro de submódulos
Para incluir archivos hermanos dentro de submódulos, como /src/house/
main_dish/lasagna.rs
dentro de diner/mod.rs
puede acceder a lasagna.rs usando el self
palabra clave en su use
declaraciones. pub mod dessert; pub mod main_dish; use self::main_dish::lasagna; // use super::diner::main_dish::lasagna; pub fn eat () { lasagna::eat_lasagna(); let candy = dessert::candy::Candy::new_chocolate( 10 ); dessert::candy::eat_dessert(candy); }
Por ejemplo, el código a continuación se usa para navegar relativamente a la ubicación del módulo actual y luego profundizarlo en el
main_dish::lasagna
.También puedes usar
super
y eso comenzará desde el módulo principal.Algunas cosas que debes saber:
- Prefiere guión bajo (caso de serpiente) sobre guiones. Estos últimos tienden a crear problemas (1) (2) .
- Para exponer módulos oxidados (archivos) dentro de un directorio (carpeta), debe crear una carpeta con el nombre del directorio y exportar en forma de
para permitir que el compilador use el archivo.pub mod file_name_inside_folder
Referencias
- Rust 2018: módulos, cajas externas, submódulos, rutas y modificadores de visibilidad de TensorProgramming: (el mejor recurso que explica cómo incluir todo) https://www.youtube.com/watch?v=U8uhW9bFm-8
- Incluidas cajas con debate entre guiones y guiones bajos: https://github.com/rust-lang/cargo/issues/2775
- https://doc.rust-lang.org/reference/visibility-and-privacy.html
- https://github.com/rust-lang/book/issues/1709
- https://stackoverflow.com/questions/57535061/how-to-use-another-file-in-rust-module-with-hyphens-in-it-
- https://users.rust-lang.org/t/how-to-call-a-function-in-other-file-but-the-same-crate/15214-
- https://stackoverflow.com/a/26390046/1057052
- https://stackoverflow.com/questions/45519176/how-do-i-use-or-import-a-local-rust-file
- https://stackoverflow.com/questions/26224947/how-do-i-do-a-basic-import-include-of-a-function-from-one-module-to-other-in-r