How do I go about initalizeing these structs


#1
struct Cell {
    value_posibilities: Vec<u8>,
    value: u8
}

struct Zone {
    zone_grid: [[Cell; 3]; 3]
}

struct Sudoku {
    main_grid: [[Zone; 3]; 3],
    set_cells_count: u8
}

how do I initialize and instance of Sudoku{}?

I have this so far.

impl Sudoku {
    fn new(mut data: Vec<u8>) -> Sudoku {
    let mut sudoku: Sudoku;
    data.reverse();
    for main_grid_row in 0..3 {
        for main_grid_col in 0..3 {
            for zone_grid_row in 0..3 {
                for zone_grid_col in 0..3 {
                    sudoku
                        .main_grid[main_grid_row][main_grid_col]
                        .zone_grid[zone_grid_row][zone_grid_col]
                        .value = data.pop().unwrap();
                     sudoku
                        .main_grid[main_grid_row][main_grid_col]    
                        .zone_grid[zone_grid_row][zone_grid_col]
                        .value_posibilities = vec![1,2,3,4,5,6,7,8,9];
                }
            }
        }
    }
    return sudoku;
}

when I attempt compile it tells me that:

Compiling rdoku v0.1.0 (file:///home/jamal/Workspace/rdoku)
src/main.rs:28:25: 31:57 error: use of possibly uninitialized variable: `sudoku.main_grid[..][..].zone_grid[..]` [E0381]
src/main.rs:28                         sudoku
src/main.rs:29                             .main_grid[main_grid_row][main_grid_col]
src/main.rs:30                             .zone_grid[zone_grid_row][zone_grid_col]
src/main.rs:31                             .value = data.pop().unwrap();
src/main.rs:28:25: 31:57 help: run `rustc --explain E0381` to see a detailed explanation
src/main.rs:32:26: 35:74 error: use of possibly uninitialized variable: `sudoku.main_grid[..][..].zone_grid[..]` [E0381]
src/main.rs:32                          sudoku
src/main.rs:33                             .main_grid[main_grid_row][main_grid_col]
src/main.rs:34                             .zone_grid[zone_grid_row][zone_grid_col]
src/main.rs:35                             .value_posibilities = vec![1,2,3,4,5,6,7,8,9];

so how do I make it so that these members are not uninitialized when I attempt assign to them?


#2

The simplest thing to do would be adding #[derive(Default)] to all structures and changing let mut sudoku: Sudoku; to let mut sudoku = Sudoku::default();


#3

This worked flawlessly. What is #[derive(Default)] doing?


#4

It adds a static default method which constructs a struct with all fields initialized to their default values. Docs. Note that this is not the flawless solution because it allows the client of Sudoku to bypass new method and invoke default directly. But Iā€™d say that simplicity beats purity in this case :wink:


#5

Just out of curiosity, what would one have to do make it so that the client could only call new() if they wanted a new instance of any said object but still having implemented default() on the object too?


#6

Hm, I think it is impossible to implement trait privately. So the only way would be to create your own private method with similar semantics manually. And creating these arrays will be a bit of a pain, because currently stable Rust lacks support for const functions and type level integers. So I would do something like

struct Cell {
    value_posibilities: Vec<u8>,
    value: u8
}

struct Zone {
    zone_grid: [[Cell; 3]; 3]
}

struct Sudoku {
    main_grid: [[Zone; 3]; 3],
    set_cells_count: u8
}

impl Sudoku {
    fn empty() -> Sudoku {
        macro_rules! three {
            ($expr:expr) => { [$expr, $expr, $expr] }
        }
        macro_rules! nine {
            ($expr:expr) => { [three!($expr), three!($expr), three!($expr)] }
        };
        Sudoku {
            main_grid: nine!(Zone {
                zone_grid: nine!(Cell { value_posibilities: Vec::new(), value: 0})
            }),
            set_cells_count: 0
        }
    }
}

#7

Another approach to representing sudoku board would be a custom Index implementation:

type SudokuIndex = ((usize, usize), (usize, usize))

struct Board {
   cells: Vec<Cell> // my len is 92
}

impl Index<SudokuIndex> for Board {
    type Output = Cell;
    ...
}

impl IndexMut<SudokuIndex> for Board {
    ...
}


#8

Another way to avoid the public default method is to have an InnerSudoku type which implements Default, and have Sudoku just wrap that and present a public interface.