是否可以指定函数的Vec
参数具有一定的长度?考虑骰子的可能值:
fn new(d_type: DiceType, face_vals: /*Vec<u32> with len() == 2/4/6/8/10/12/20*/) -> Dice {...}
我正在写一些东西,让您创建具有指定面值的多面骰子(通常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
}
}
答案
可接受的答案表明可以很好地利用结果来返回值,但是响应使我开始思考如何使代码更灵活,同时仍然具有可以保证单卷溢出安全性的硬上限,因此我切出了一堆代码,并提出了以下内容,可以让您生成每卷介于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,
}
}
}
}
答案 0 :(得分: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]),
}
那么您就不能拥有无效的值:
fn take_a_dice(_dice: Dice) {
//
}
fn main() {
take_a_dice(Dice::D4([1, 2, 4, 8]));
}
答案 1 :(得分:3)
您应该使用Result
来解释可能的错误输入:
use std::cmp::Ordering;
#[derive(Clone, Copy)]
pub enum DiceType {
D2,
D4,
D6,
D8,
D10,
D10P,
D12,
D20
}
pub struct Dice {
dice_type: DiceType,
// no need for face_count, it's a method of DiceType
face_values: Vec<u32>
}
// an error for invalid face value inputs
enum DiceError {
TooFewFaceValues,
TooManyFaceValues
}
impl DiceType {
fn face_count(&self) -> usize {
match self {
DiceType::D2 => 2,
DiceType::D4 => 4,
_ => unimplemented!() // TODO: account for all the other variants
}
}
}
impl Dice {
fn new(dice_type: DiceType, face_values: &[u32]) -> Result<Self, DiceError> {
match face_values.len().cmp(&dice_type.face_count()) {
Ordering::Less => Err(DiceError::TooFewFaceValues),
Ordering::Greater => Err(DiceError::TooManyFaceValues),
Ordering::Equal => Ok(
Dice {
dice_type,
face_values: Vec::from(face_values)
}
)
}
}
}