如何确保我的功能将获得有效长度的Vec?

Ver*_*gil 1 rust

是否可以指定函数的Vec参数具有一定的长度?考虑骰子的可能值:

fn new(d_type: DiceType, face_vals: /*Vec<u32> with len() == 2/4/6/8/10/12/20*/) -> Dice {...}
Run Code Online (Sandbox Code Playgroud)

我正在写一些东西,可以让你创建一个具有指定面值的多面体骰子(通常的RPG大小:2,4,6等).我记得当你在没有unsafe关键字的情况下调用Rust函数时,用户应该可以调用它,但是他们喜欢而不用担心失败,因此只需检查函数的有效性并返回一些"搞砸了"错误就是Rust.

我怎样才能做到这一点?

这是我正在处理的代码的一部分:

pub enum DiceType {
    D2,
    D4,
    D6,
    D8,
    D10,
    D10P,
    D12,
    D20,
}

pub struct Dice {
    dice_type: DiceType,
    face_count: usize,
    face_values: Vec<u32>,
}

impl Dice {
    pub fn new(d_type: DiceType, face_vals: Vec<u32>) -> Dice {
        let mut retval;

        //Reject if not a valid dice type 2, 4, 6, 8, 10, 12, or 20
        //I really shouldn't be doing this should I?
        if Dice::valid_dice(d_type, face_vals) {
            retval = Dice {
                dice_type: d_type,
                face_count: face_vals.len(),
                face_values: face_vals,
            }
        } else {
            //User wont know they got an error
            //Really shouldn't need to go here. How do I avoid needing
            //error checking?
            retval = Dice {
                dice_type: None,
                face_count: 2,
                face_values: face_vals,
            };
        }

        retval
    }
}
Run Code Online (Sandbox Code Playgroud)

回答

接受的答案显示了很好地利用结果返回一个值,但响应让我思考如何使代码更灵活,同时仍然有一个硬盘,可以保证单个卷的溢出安全性,所以我删除了一堆代码并提出以下内容,可让您生成每卷1-10,000之间的骰子卷,并带有额外卷的乘数.

const MAX_FACE_VALUE: u32 = 100000;
const MAX_FACE_COUNT: u32 = 10000;
const MAX_ROLL_COUNT: u32 = 9999;

pub struct Dice {
    face_count: usize,
    face_values: Vec<u32>,
}

impl Dice {
    pub fn new(mut face_vals: Vec<u32>) -> Self {
        //User may not have values greater than 100,000
        //Index access is safe since we use the for _ in _
        for x in 0..face_vals.len() {
            if face_vals[x] > MAX_FACE_VALUE {
                //Enforce the limit
                face_vals[x] = MAX_FACE_VALUE;
            }
        }

        //User may not have more than 10,000 faces
        if face_vals.len() > MAX_FACE_COUNT as usize {
            let new_vals: Vec<u32> = face_vals.split_off(MAX_FACE_COUNT as usize);
            Dice {
                face_count: MAX_FACE_COUNT as usize,
                face_values: new_vals,
            }
        } else if face_vals.len() == 0 {
            //No 0 sided dice allowed
            Dice {
                face_count: 1,
                face_values: vec![1],
            }
        } else {
            //Normal range
            Dice {
                face_count: face_vals.len(),
                face_values: face_vals,
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Fre*_*ios 7

您应该使用具有固定长度的相应数组的变体的枚举:

#[derive(Clone, Copy)]
pub enum Dice {
    D2([u32; 2]),
    D4([u32; 4]),
    D6([u32; 6]),
    D8([u32; 8]),
    D10([u32; 10]),
    D10P([u32; 10]),
    D12([u32; 12]),
    D20([u32; 20]),
}
Run Code Online (Sandbox Code Playgroud)

那么你不能有无效的价值:

fn take_a_dice(_dice: Dice) {
    //
}

fn main() {
    take_a_dice(Dice::D4([1, 2, 4, 8]));
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这是功能编程中的一般咒语(Rust借用了很多东西):*不允许表示无效数据*. (4认同)