[Solved] Modules multiples crates... what is the best pattern to use to get multiple files and dirs in my project?

Hello All,

I'm from Java... I just started using rust to day.

I just want to have a rust app in multiple .rs and directories in oder to spilt my app in multiple technical and functional domains?

I saw both references:

This is confusing!!

Theoretically you could do either to manage a project, but it's preference about the model for your project. So if for example you're building something like piston you end up with multiple crate in the same repository because of the size of each of the individual parts: pistoncore-window, pistoncore-input and pistoncore-event_loop. You could have a single crate, with multiple third party dependencies or even just stuff a bloated project into the same crate (Although if it's bloated, think about migrating to separate repositories). Realistically it's just your opinion.

Rust community is super fast to reply. thanks @OptimisticPeach ... Currently I fail to use both approach

with modules:

├── Cargo.toml
└── src
    ├── fib
    │   ├── fibonacci.rs
    │   └── mod.rs
    └── main.rs

in mod.rs

pub mod fibonacci;

in fibonacci.rs

use std::collections::HashMap;

const X_0: u64 = 1;
const X_1: u64 = 1;

pub fn fb(x: u64, map: &mut HashMap<u64, u64>) -> u64 {
    match x {
        0 => X_0,
        1 => X_1,
        n => {
            if map.contains_key(&n) { return *map.get(&n).unwrap(); } else {
                let local_result = fb(n - 1, map) + fb(n - 2, map);
                map.insert(n, local_result);
                return local_result;
            }
        }
    }
}

in main.rs

use std::collections::HashMap;
mod fib;
use fib::fibonacci::fb;

fn main() {
   let mut map: HashMap<u64, u64> = HashMap::new();
   fb(1,&mut map);
}

in Cargo.toml

[package]
name = "learnRust"
version = "0.1.0"
edition = "2018"

[dependencies]

fails with

$ cargo run
   Compiling learnRust v0.1.0 (/Users/jpiraguha/dev/rust/packtpub/learnRust)                                     
error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
 --> src/main.rs:3:5                                                                                             
  |                                                                                                              
2 | mod fib;                                                                                                     
  | -------- not an extern crate passed with `--extern`                                                          
3 | use fib::fibonacci::fb;                                                                                      
  |     ^^^                                                                                                      
  |                                                                                                              
note: this import refers to the module defined here                                                              
 --> src/main.rs:2:1                                                                                             
  |                                                                                                              
2 | mod fib;                                                                                                     
  | ^^^^^^^^                                                                                                     
                                                                                                                 
error: aborting due to previous error  

What is wrong?

Oh, this is something that gets me frequently, if you define a module:

mod fib;

and you want to bring all of its items into scope, or even one of its items, you have to do it like so:

use self::fib::*;
1 Like

Thanks so much @OptimisticPeach ... Not trivial but this is clearer to me:

for the other approach works to with:

├── Cargo.toml
├── fib
│   ├── Cargo.toml
│   └── src
│       ├── fibonacci.rs
│       └── lib.rs
├── src
│   └── main.rs
└── target

in main.rs

extern crate fib;
use fib::fibonacci::fb;
...

in the root Cargo.toml

[package]
name = "learnRust"
version = "0.1.0"
edition = "2018"

[dependencies]

[dependencies.fib]
path = "fib"

[workspace]
members = [
    "fib"
]

in Cargo.toml in fib

[package]
name = "fib"
version = "0.1.0"
edition = "2018"

[dependencies]

in lib.rs

pub mod fibonacci;

This is quite declarative. Is there a CLI or intellij support to improve productivity there? ?

1 Like

extern crate is not needed any more since the 2018 edition.

[workspace] is optional. You can use path dependencies without it (but you might need to put it in ../fib so that Cargo doesn't think you're trying to make a workspace).

Libraries often do pub use crate::fibonacci::fb in their lib.rs, so that users of the library don't have to use long module path names, and can use fib::fb instead.

1 Like

Oh... Much better and cleaner :slight_smile: thanks @kornel !

Hey for mod stuff I found another way to avoid the error <not an extern crate passed with --extern>:

mod helper_module;
use crate::fib::fibonacci::fb;

Maybe this is equivalent to what you proposed?:

mod helper_module;
use self::fib::fibonacci::fb;

The keywords "self" and "crate" at the import are still obscure to me.

self in that case refers to the current context, which in this case happens to be the crate root, but it could be for example foo::bar::baz
crate refers to the project root l, and only of your project
::<foo> refers to the root namespace and you can access anything in any crate
(Where <foo> is replaced with the module you want to go into)

1 Like

Oh, by the way in rust 1.32 you don't need to use the self keyword to access members in your own module, and are instead automatically included in your namespace.