paint-brush
Incluir archivos y directorios profundos en Rustpor@josejaviasilis
26,598 lecturas
26,598 lecturas

Incluir archivos y directorios profundos en Rust

por Jose Javi Asilis6m2020/03/26
Read on Terminal Reader
Read this story w/o Javascript

Demasiado Largo; Para Leer

Rust no ve los archivos como archivos, pero los ve como módulos y los archivos dentro de las carpetas como submódulos. 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. Cuando usa crate, usa el directorio raíz para incluir todo. Rust puede ayudar al compilador de Rust a identificarlo proporcionando una directiva #path para usar en nuestro código de bienvenida. Entonces podemos hacer referencia a él directamente para llamar directamente a la función de ejecución.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Incluir archivos y directorios profundos en Rust
Jose Javi Asilis HackerNoon profile picture

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
    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.
  • 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
    función. Como está en el mismo archivo, solo puede
     building::lobby::arrive_lobby
    y el módulo es visible.
  • Puede usar un recurso directamente especificándolo con el
     use
    palabra clave. Esto significa que no necesita escribir
     house::bathroom:sink::wash_face()
    usar la función, pero simplemente
     wash_face()
    .
  • En caso de
     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
    .
  • Después
     use
    , si escribes
     crate
    , le está diciendo al compilador que comience a buscar desde el directorio raíz.
  • 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)
    función y enumeración, solo especifiqué
     mod house
    , y luego desglosé los espacios de nombres con los dos puntos dobles (::) hasta que llegué.

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
     pub mod file_name_inside_folder
    para permitir que el compilador use el archivo.

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