Reputation: 23
I am new to Rust, and have gotten some way through writing my first toy program, just a card game implementation. Here is my current file structure:
├── Cargo.lock
├── Cargo.toml
├── src
│ ├── card.rs
│ ├── deck.rs
│ ├── hand.rs
│ └── main.rs
The basic building block of course being the card struct, it looks like this:
pub struct Card {
value: Value,
suit: Suit,
is_visible : bool
}
impl Card {
pub fn new(value: &Value, suit: &Suit) -> Card {
Card {...}
}
}
#[derive(Clone)]
pub enum Suit {...}
#[derive(Clone)]
pub enum Value{...}
Deck implementation in deck.rs, using the card module:
#[path="card.rs"]
mod card;
pub use card::*;
pub struct Deck(Vec<Card>);
impl Deck {
pub fn new(n_packs: u32) -> Deck {
let mut cards = Vec::new();
...
Deck(cards)
}
pub fn deal_from_top(&mut self, n_cards: u32) -> Vec<Card>{...}
pub fn shuffle(&mut self) {...}
...
}
very similar struct, Hand is defined in module hand.rs
#[path = "card.rs"]
mod card;
pub use card::*;
pub struct Hand(Vec<Card>);
impl Hand{
pub fn new(cards: Vec<Card>) -> Hand{
Hand(cards)
}
}
In main.rs, I have want to
That last one is giving me some serious grief.
Here is what I have tried:
mod hand;
mod deck;
use hand::Hand;
use deck::Deck;
fn main() {
let mut deck = Deck::new(1);
deck.shuffle();
let mut cards = deck.deal_from_top(5);
let mut hand = Hand::new(cards);
}
Which throws a complie-time error E0308:
error[E0308]: mismatched types
--> src/main.rs:13:30
|
13 | let mut hand = Hand::new(cards);
| ^^^^^ expected struct `hand::card::Card`, found struct `deck::card::Card`
|
= note: expected struct `std::vec::Vec<hand::card::Card>`
found struct `std::vec::Vec<deck::card::Card>`
So clearly I am missing something in my understanding of how user-defined types are 'imported' for use.
By importing the cards module, the 'Card' type used by deck, and by hand become separate types as far as main is concerned. I do not want deck or hand to reference each other to access the same namespaced version of Card.
How can I make the card struct completely reusable in this context? or is my somewhat object-oriented approach just so wide of the mark to not be achievable in idiomatic rust? Searching so far has yielded nothing.
Upvotes: 2
Views: 559
Reputation: 16910
With #[path="card.rs"]
you force your deck
and hand
modules to find the card
submodule in a non-standard place.
In deck.rs
and hand.rs
, writing mod card;
considers card
as a submodule of the two previous.
In theory, these submodules should be located in src/deck/card.rs
and src/hand/card.rs
, hence the path=
notation to find these in another place.
Instead of that, you probably want to use the card
module which is at the same level.
Just get rid of mod card;
in those two files and write pub use super::card::*;
instead of pub use::card::*;
. Finally, add mod card;
in main.rs
so that it is discovered when main.rs
is read by the compiler.
In your solution, reusing the same file for two different submodules was just a trick equivalent to copy/paste but from the language point of view, these two submodules and the struct they provide are distinct (as told by the compiler in the error message).
Upvotes: 6