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
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.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" ); } } }
mod
y el nombre del archivo (sin la extensión .rs). Por ejemplo: modo welcome_home
. En este caso, welcome_home no coincide con el nombre del archivo ( welcome-home.rs
- Evite el uso de guiones al nombrar todo; esto fue para mostrar que es posible, no que deba hacerse ) , por lo tanto, podemos ayudar al compilador de Rust a identificarlo proporcionando una directiva #path. Entonces podemos hacer referencia en nuestro código welcome_home::run()
para llamar a la función de ejecución directamente. arrive_lobby
función. Como está en el mismo archivo, solo puede building::lobby::arrive_lobby
y el módulo es visible. use
palabra clave. Esto significa que no necesita escribir house::bathroom:sink::wash_face()
usar la función, pero simplemente wash_face()
. wash_face
que se encuentra en house::bathroom::sink::wash_face
primero cree un archivo house.rs en el directorio de nivel raíz o un archivo mod.rs en /src/house/mod.rs. Dentro especifica los nombres de las carpetas que se incluyen dentro de /src/house: pub mod bathroom
. Crear un bathroom.rs
presentar en /src/house/bathroom.rs
y dentro especifica los módulos (nombres de archivo sin la extensión .rs) dentro /src/house/bathroom
: pub mod sink; pub mod shower; pub mod toilet;
Nota la pub
modificador ya que esto es lo que da visibilidad fuera del archivo especificado. Luego inclúyalos en el código a través de use house::bathroom::sink::wash_face
. use
, si escribes crate
, le está diciendo al compilador que comience a buscar desde el directorio raíz. house::bathroom::shower::take_shower(house::bathroom::shower::ShowerTemperature::Cold)
función y enumeración, solo especifiqué mod house
, y luego desglosé los espacios de nombres con los dos puntos dobles (::) hasta que llegué.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.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. pub mod file_name_inside_folder
para permitir que el compilador use el archivo.