web-dev-qa-db-fra.com

Comment faire une importation / inclusion de base d'une fonction d'un module à un autre en Rust 2015?

Je ne trouve pas comment inclure (ou importer, injecter ou un autre Word) une fonction d'un fichier (module) à un autre.

Je démarre un nouveau projet avec

$ cd ~/projects
$ cargo new proj --bin
$ cd proj
$ tree
.
|
-- Cargo.toml
-- src
   |
   -- main.rs

Je modifie main.rs et créez un nouveau fichier a.rs (à l'intérieur du répertoire src) avec le code suivant:

main.rs

fn main() {
    println!("{}", a::foo());
}

a.rs

pub fn foo() -> i32 { 42 }

Je gère le projet avec cargo run et obtenez l'erreur:

error[E0433]: failed to resolve: use of undeclared type or module `a`
 --> src/main.rs:2:20
  |
2 |     println!("{}", a::foo());
  |                    ^ use of undeclared type or module `a`

Il semble que je doive importer le a d'une manière ou d'une autre. J'ai essayé d'ajouter les éléments suivants en première ligne à main.rs

  • use a;

    error[E0432]: unresolved import `a`
     --> src/main.rs:1:5
      |
    1 | use a;
      |     ^ no `a` in the root
    
  • use a::*;

    error[E0432]: unresolved import `a`
     --> src/main.rs:1:5
      |
    1 | use a::*;
      |     ^ maybe a missing `extern crate a;`?
    
    error[E0433]: failed to resolve: use of undeclared type or module `a`
     --> src/main.rs:4:20
      |
    4 |     println!("{}", a::foo());
      |                    ^ use of undeclared type or module `a`
    
  • use a::foo;

    error[E0432]: unresolved import `a`
     --> src/main.rs:1:5
      |
    1 | use a::foo;
      |     ^ maybe a missing `extern crate a;`?
    
    error[E0433]: failed to resolve: use of undeclared type or module `a`
     --> src/main.rs:4:20
      |
    4 |     println!("{}", a::foo());
      |                    ^ use of undeclared type or module `a`
    
  • extern crate a; use a::foo;

    error[E0463]: can't find crate for `a`
     --> src/main.rs:1:1
      |
    1 | extern crate a;
      | ^^^^^^^^^^^^^^^ can't find crate
    
  • extern crate proj; use proj::a::foo;

    error[E0463]: can't find crate for `proj`
     --> src/main.rs:1:1
      |
    1 | extern crate proj;
      | ^^^^^^^^^^^^^^^^^^ can't find crate
    

J'ai lu le guide mais je ne sais toujours pas comment faire des importations.

41
vil

Dans un module principal (main.rs, lib.rs ou subdir/mod.rs), vous devez écrire mod a; pour tous les autres modules que vous souhaitez utiliser dans l'ensemble de votre projet (ou dans le sous-répertoire).

Dans tout autre module, vous devez écrire use a; ou use a::foo;

Vous êtes loin d'être la seule personne à être confus par cela, et il est certainement possible de faire mieux, mais toute modification du système de modules sera rejetée comme "trop ​​confuse".

Edit: cette réponse a été écrite pour la norme de langue "Rust 2015". Des modifications ont été apportées à la norme "Rust 2018", voir cet article de blog et guide d'édition

38
o11c

Dans Rust, il y a quelques mots clés pour gérer les modules:

extern crate

extern crate comble l'écart entre Cargo et Rust. Nous écrivons du code dans un fichier .rs, ce fichier peut être compilé avec rustc. Cargo gérera les dépendances externes et appellera rustc. Le extern crate ... line indique au compilateur de rechercher cet espace de noms, il n'est donc pas ambigu.

NDLR - extern crate n'est pas requis dans de nombreux cas si vous utilisez l'édition Rust 2018.

mod

mod a deux utilisations:

  • lorsqu'il est utilisé avec des accolades, il déclare un module (espace de noms).
  • lorsqu'il est utilisé avec juste un nom, il recherchera le module dans le système de fichiers local.

Les modules peuvent être:

  • fichiers avec l'extension .rs
  • dossiers avec un fichier appelé mod.rs

use

use importe un espace de noms. Nous sommes tenus d'annoncer ce que nous allons utiliser avant de l'utiliser. La clause use est assez stricte, si nous déclarons use module1::moduleA; aucun autre module de module1 sera disponible mais moduleA. Un astérisque (*) peut être utilisé pour tout utiliser dans un module: use module1::*;. Les ensembles peuvent également être utilisés: use module1::{moduleA, moduleB};

Un exemple:

| main.rs
|- module1
      |- mod.rs
      |- moduleA.rs
      |- moduleB.rs

mod.rs contient:

pub mod moduleA; // declare a child module
pub mod moduleB; // declare a child module

main.rs contient:

///  ======
// 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();
}

Les symboles ne sont utilisables que depuis le module. Si vous voulez franchir cette barrière (même sur un module déclaré localement), nous devons les rendre publics en utilisant le mot clé pub.

15
Luis Ayuso