Включая файлы и глубокие каталоги в Rust

Новички в Rust критиковали механизм включения файлов. Около 2 дней назад я потратил около 5 часов на то, как я должен был включить файл, на который ссылались в глубине дерева каталогов. Документы не помогли, так как они были простыми структурами. Здесь я покажу вам, как вы можете включить свой код в различные части приложения, даже когда структура сложна, и сэкономит вам часы на том, как выполнить эту якобы тривиальную задачу.

Я собираюсь сослаться на признаки, модули, перечисления, функции, структуры как «ресурсы» в целом.

Там нет такой вещи, как «файл», когда вы ссылаетесь на свой ресурс.

Rust не видит файлы как файлы, но видит их как модули, а файлы внутри папок — как подмодули. Поэтому вы не можете просто ссылаться на них напрямую с помощью простого импорта или детализированного пространства имен в виде JavaScript или C # и использовать их сразу.

Вам нужно создать дерево

pub mod file_name

(В мире JS называется бочонком), которые открывают эти модули для внешних и (см. Пункты ниже) позволяют их обнаруживать и использовать.

Как включить модуль (файл)

Давайте предположим, что у нас есть следующая структура (Вы можете получить это из Сделки рЕПО).
И вы хотели бы включить несколько функций из модулей, разбросанных внутри

/src/house

каталог в наш

main.rs

файл:

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");
        }
    }
}
  • Чтобы включить файл рядом с файлом main.rs, вы просто указываете
    mod 

    и имя файла (без расширения .rs). Например: мод

    welcome_home

    , В этом случае welcome_home не совпадает с именем файла (

    welcome-home.rs

    Избегайте использования дефисов в именовании всего; это должно было продемонстрировать, что это возможно, не то, что это должно быть сделано)поэтому мы можем помочь компилятору Rust определить его, предоставив директиву #path. Тогда мы можем ссылаться в нашем коде

    welcome_home::run() 

    вызвать функцию запуска напрямую.

  • Чтобы использовать мод, который существует внутри файла, вы можете просто ввести его имя в качестве пространства имен и перейти к нужному ресурсу. Следует понимать, что если модуль не является общедоступным, вы не сможете получить к нему доступ в своем файле. Проверьте Справочник по видимости и конфиденциальности Rust для дополнительной информации. Если вы хотите включить
    arrive_lobby

    функция. Поскольку он находится в одном файле, вы можете просто

    building::lobby::arrive_lobby

    и модуль виден.

  • Вы можете использовать ресурс напрямую, указав его с помощью
    use

    ключевое слово. Это означает, что вам не нужно писать

    house::bathroom:sink::wash_face()

    использовать функцию, но просто

    wash_face()

    ,

  • В случае
    wash_face 

    который находится в

    house::bathroom::sink::wash_face

    сначала создайте файл house.rs в корневом каталоге или файл mod.rs в /src/house/mod.rs. Внутри него укажите имена папок, которые включены в / src / house:

    pub mod bathroom

    , Создать

    bathroom.rs

    файл в

    /src/house/bathroom.rs

    и внутри него укажите модули (имена файлов без расширения .rs) внутри

    /src/house/bathroom

    :

    pub mod sink; pub mod shower; pub mod toilet; 

    Обратите внимание

    pub

    модификатор, поскольку это то, что дает видимость за пределами указанного файла. Затем включите их в код через

    use house::bathroom::sink::wash_face

    ,

  • После
    use

    , если вы введете

    crate

    вы говорите компилятору начать поиск из корневого каталога.

  • Если вы ссылаетесь на ресурс через мод и этот ресурс глубоко вложен, вы указываете только первый уровень модуля, а затем углубляетесь в него. Например: в случае
    house::bathroom::shower::take_shower(house::bathroom::shower::ShowerTemperature::Cold)

    Функция и перечисление, я только указал

    mod house

    , а затем просверлил пространства имен с двойным двоеточием (: :), пока я не достигну его.

Включая файлы или модули из другой папки, каталога или субмодуля

Это, пожалуй, самый хитрый и неестественный способ для всех новых людей в Rust ссылаться на модули в других файлах.

wash_face

Функция является примером глубоко вложенной функции. Я призываю вас увидеть Сделки рЕПО чтобы лучше понять, как все работает.

Ржавчина следует соглашению: Тебе нужно создать файл с именем каталога, к которому вы хотите получить доступ, и поместите его рядом с каталогом, к которому вы хотите получить доступ.

Затем вам нужно будет предоставить каждый из файлов в каталоге, который вы хотите, чтобы компилятор сделал его доступным:

Пример:

Я хотел бы получить доступ к содержимому

shower.rs

,

sink.rs

, и

toilet.rs

внутри

/src/house/bathroom

папки.

Во-первых, мне нужно создать

/src/house/bathroom.rs

файл, который сделает видимым или ствол

shower.rs,
sink.rs 

и

toilet.rs

файлы. Внутри него я бы указывал имя каждого из файлов как публичные модули:

// Contents of /src/house/bathroom.rs
pub mod shower;
pub mod sink;
pub mod toilet;
Тогда мне нужно разоблачить это

bathroom.rs

файл из

/src/house

каталог. Для этого мне нужно создать

/src/house.rs

файл, который будет экспортировать

bathroom.rs

файл, который я только что определил сейчас.

// Contents of /src/house/mod.rs or /src/house.rs
pub mod bathroom;
pub mod diner;
pub mod kitchen;
Как вы видете

pub mod bathroom

марки

bathroom.rs

файл виден Обратите внимание на соглашение:

pub mod file_name_without_rs_extension

Вы должны сделать это каждый раз Вы хотите сделать модуль (файл) видимым для внешнего модуля (каталог / папка).

Заметка: Вы увидите в репо и на картинке выше, что есть

mod.rs

файлы; В версиях до Rust 2018 единственный способ для Rust обнаружить эти каталоги — указать им

mod.rs

внутри каталога.

Это стало проблематичным, потому что, если вы захотите указать файл с тем же именем каталога, компилятор запутается. Вот почему начиная с Rust 2018 (ищите строку, которая говорит

edition = "2018"

в вашем

cargo.toml

файл).

В этом примере

/src/house/mod.rs

такой же как

/src/house.rs

Вы можете создать любой из этих файлов, и он будет работать.

Включение других родственных модулей (файлов) в подмодули

Чтобы включить дочерние файлы в подмодули, такие как / src / house /

main_dish/lasagna.rs

в пределах

diner/mod.rs

файл, который вы можете получить в lasagna.rs с помощью

self 

ключевое слово в вашем

use

заявления.

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);
}
Например, приведенный ниже код использует self для навигации относительно местоположения текущего модуля, а затем развернуть его до

main_dish::lasagna

,

Вы также можете использовать

super

и это начнется с родительского модуля.

Некоторые вещи, которые вы должны знать:

использованная литература

  • Rust 2018 — Модули, внешние ящики, подмодули, пути и модификаторы видимости от TensorProgramming — (Лучший ресурс, который объясняет, как включить все) https://www.youtube.com/watch?v=U8uhW9bFm-8
  • Включая ящики с дефисом против дискуссии о подчеркивании: 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-another-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-another-in-r



Источник: Включая файлы и глубокие каталоги в Rust


Похожие материалы по теме: Включая файлы и глубокие каталоги в Rust

Leave a comment