Home > Blockchain >  What should the default value of this match statement be, also is there a way to unwrap a Some case
What should the default value of this match statement be, also is there a way to unwrap a Some case

Time:11-09

I have a board whitch i am able to index with a glam::IVec2

struct Board{pieces: [char;64]}
type PieceOption = Option<char>;

this index method for board is

impl Index<IVec2> for Board {
    type Output = PieceOption;
    fn index(&self, v : IVec2) -> &Self::Output{
        if (v.abs() != v) || (v.max_element() > 8) {&None}
        else {
            let i : usize = (v.x   8* v.y).try_into().unwrap();
            &Some(self.pieces[i])
        }
    }
}

Along with this PieceOption has methods is_empty, is_ally and is_rival so my question is as follows: what should the value of this recursive function be, in order to achieve type consistency i need the function to return a vector but i dont want to return the vector in the case where the next piece is of the same colour (is_ally). Along with this i was wondering if there is a way of unwrapping the Some values so that i do not need to type Some('char') for every single branch in the match statement, especially since i already filtered for the cases where the next move is out of bounds. this is the current function with the type inconsistency. This is the function currenty implimented for the bishops only my intention is to feed this function consts for each of the movement types eg

const DIAGONALS : [IVec2; 4] = [
    ivec2(-1, -1), ivec2(-1, 1),
    ivec2(-1, 1), ivec2(1, 1)
];

so here is the current state of the function

impl Board {
    fn moves(&self, piece:&PieceOption, pos:IVec2, dir: Vec<IVec2>)->Vec<IVec2>{
        dir.into_iter()
            .map(|d| d pos)
            .filter(|p| (p.abs() == *p) && p.max_element() < 8)
            .flat_map(|p|
                match piece{
                    Some('B')|Some('b')=>{
                        if self[p].is_empty() {self.moves(piece, p, vec![p-pos]).push(p)}
                        else if self[p].is_rival(*piece) {p}
                        else {()} /* here is where i do not wish to return a vector because
 this is likely a case where the next piece is an opponent*/
                        },
                    _ => () /* here is where i  do not wish to return a vector because 
the piece is likely empty space*/
                }
            )
            .collect()
    }
}

UPDATE: update i have realised if let is what i need to unwrap the option of the piece but i am really confused about what the return value of the if let statement should be, my current code for the function is

impl Board {
    fn moves(&self, piece:&PieceOption, pos:IVec2, dir: Vec<IVec2>)->Option<Vec<IVec2>>{
        dir.into_iter()
            .map(|d| d pos)
            .filter(|p| (p.abs() == *p) && p.max_element() < 8)
            .flat_map(|p|
                if let Some(c) = piece{
                    match c{
                        'B'|'b'=>{
                            if self[p].is_empty() {self.moves(piece, p, vec![p-pos])?.push(p)}
                            else if self[p].is_rival(*piece) {Some(vec![p])}
                            else {None?}
                            },
                        _ => None
                        }
                } else {None}   
            )
            .collect()
    }
}

Along with this any advice on the format is greatly appreciated I'd like to know what people think about this potential solution and my appologies if the question is confusingly worded? full code can be found at: https://github.com/LyndonAlcock/chess_test

CodePudding user response:

The return type of a closure passed to flat_map should be a collection. If you don't want to add anything you can just return an empty one. vec![] in case of a Vec

Also Option<char> is copy so you can just pass in the thing instead of a reference.

impl Board {
    fn moves(&self, piece: PieceOption, pos: IVec2, dir: Vec<IVec2>) -> Vec<IVec2> {
        dir.into_iter()
            .map(|d| d pos)
            .filter(|p| (p.abs() == *p) && p.max_element() < 8)
            .flat_map(|p|
                if let Some(c) = piece {
                    match c {
                        'B'|'b'=> {
                            if self[p].is_empty() {
                                let moves = self.moves(piece, p, vec![p-pos])
                                moves.push(p);
                                moves
                            } else if self[p].is_rival(*piece) {
                                vec![p]
                            } else {
                                vec![]
                            }
                        },
                        _ => vec![]
                        }
                } else {
                    vec![]
                }
            )
            .collect()
    }
}
  • Related