Основной импорт ржавчины (включая)
Я действительно не могу найти, как включать (или импортировать, вводить или smth.) Функцию из одного файла (модуля) в другой.
Вот пример.
Я начинаю новый проект с
cd ~/projects
cargo new proj --bin
cd proj
tree
# output
.
|
-- Cargo.toml
-- src
|
-- main.rs
Затем я main.rs
и создаю новый файл a.rs
(внутри a.rs
src
) со следующим кодом:
// main.rs
fn main() { println!("{}", a::foo()); }
// a.rs
pub fn foo() -> int { 42i }
Я запускаю проект с cargo run
Здесь у меня две ошибки:
- src/main.rs: 2: 20: 2:26 Ошибка: не удалось разрешить. Использование незаявленного модуля
a
- src/main.rs: 2: 20: 2:26 error: unresolved name
a::foo
.
Пока это кажется совершенно очевидным, мне просто нужно каким-то образом импортировать a
.
Я попытался добавить следующие вещи в качестве первой строки в main.rs
-
use a;
→ ошибка: неразрешенный импорт (возможно, вы имели a::*
виду a::*
?) -
use a::*;
→ ошибка: операторы импорта glob являются экспериментальными и, возможно, ошибками -
use a::foo;
→ ошибка: неразрешенный импорт a::foo
. Может быть, недостающий extern crate a
? -
extern crate a; use a::foo;
→ Ошибка: не удается найти ящик для a
-
extern crate proj; use proj::a::foo;
→ ошибка: не удается найти ящик для proj
Я прочитал руководство на ржавчине, но до сих пор не могу понять, как делать импорт.
Ответы
Ответ 1
В основном модуле (main.rs, lib.rs или subdir/mod.rs) вам нужно написать mod a;
для всех остальных модулей, которые вы хотите использовать во всем проекте (или в поддиректории).
В любом другом модуле вам нужно написать use a;
или use a::foo;
Вы далеко не единственный, кого это смущает, и, безусловно, можно добиться большего, но любые изменения в модульной системе будут отклонены как "слишком запутанные".
Изменение: этот ответ был написан для языкового стандарта "Rust 2015". Изменения были внесены в стандарт "Rust 2018", см. Этот пост в блоге.
Ответ 2
В Rust есть несколько ключевых слов для работы с модулями:
extern crate
extern crate
заполняет пробел между Cargo и Rust. Мы пишем код в файле .rs, этот файл может быть скомпилирован с помощью rustc
. Cargo будет управлять внешними зависимостями и вызывать rustc
. Строка extern crate...
указывает компилятору искать это пространство имен, поэтому оно однозначно.
Примечание редактора - extern crate
не требуется во многих случаях, если вы используете версию Rust 2018.
mod
mod
имеет два применения:
- при использовании с фигурными скобками он объявляет модуль (пространство имен).
- при использовании только с именем, он будет искать модуль в локальной файловой системе.
Модули могут быть:
- файлы с расширением .rs
- папки с одним файлом с именем mod.rs
use
use
импортирует пространство имен. Мы должны объявить, что мы собираемся использовать, прежде чем использовать его. Предложение use довольно строгое, если мы use module1::moduleA;
Никакой другой модуль из модуля module1
не будет доступен, кроме moduleA
Звездочка (*
) может использоваться для использования всего в модуле: use module1::*;
, Также можно использовать наборы: use module1::{moduleA, moduleB};
Пример:
| main.rs
|- module1
|- mod.rs
|- moduleA.rs
|- moduleB.rs
mod.rs содержит:
pub mod moduleA; // declare a child module
pub mod moduleB; // declare a child module
main.rs содержит:
/// ======
// use what Cargo downloaded
extern crate that_one_thing_i_need;
/// ======
mod module1; // declare a child module
// some local stuff I want to scope
mod local {
pub fn my_function() {}
}
// ======
// make the symbols locally available:
use module1::moduleA::*;
use module1::moduleB::{functionX, moduleY, typeZ};
// we still need to announce what stuff from the external crate
// we want to use:
// We can do local aliases that will be valid in this one file.
use that_one_thing_i_need::fancy_stuff as fs;
/// ======
fn main() {
// we can use anything here from the namespaces we are using:
// moduleA
// functionX
// moduleY
// typeZ
// fs
// We can access stuff by navigating from the outermost visible
// module name
local::my_function();
}
Символы можно использовать только из модуля. Если вы хотите преодолеть этот барьер (даже в локально объявленном модуле), нам нужно сделать их общедоступными с помощью ключевого слова pub
.