Rust 如何确保我的函数将收到有效长度的Vec?
是否可以指定函数的Rust 如何确保我的函数将收到有效长度的Vec?,rust,Rust,是否可以指定函数的Vec参数具有一定的长度?考虑骰子的可能价值: fn new(d_type: DiceType, face_vals: /*Vec<u32> with len() == 2/4/6/8/10/12/20*/) -> Dice {...} 回答 被接受的答案显示了返回值的结果的良好用途,但响应让我思考如何使代码更灵活,同时仍然有一个硬帽,可以保证单掷的溢出安全,因此我删掉了一堆代码,并提出了以下内容,这应该可以让你每掷1-10000个骰子使用倍增器进行额外掷骰
Vec
参数具有一定的长度?考虑骰子的可能价值:
fn new(d_type: DiceType, face_vals: /*Vec<u32> with len() == 2/4/6/8/10/12/20*/) -> Dice {...}
回答
被接受的答案显示了返回值的结果的良好用途,但响应让我思考如何使代码更灵活,同时仍然有一个硬帽,可以保证单掷的溢出安全,因此我删掉了一堆代码,并提出了以下内容,这应该可以让你每掷1-10000个骰子使用倍增器进行额外掷骰
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,
}
}
}
}
常数最大值:u32=100000;
const MAX_FACE_COUNT:u32=10000;
常量最大滚动计数:u32=9999;
pub结构骰子{
面部计数:使用,
面值:Vec,
}
插入骰子{
发布fn新(多个面:Vec)->Self{
//用户的值不能大于100000
//索引访问是安全的,因为我们在_
对于0..face_vals.len()中的x{
如果面值[x]>最大面值{
//执行限制
面值[x]=最大面值;
}
}
//用户不能有超过10000个面
如果face\u vals.len()>MAX\u face\u算作usize{
让新值:Vec=face\u vals.split\u off(MAX\u face\u计为usize);
掷骰子{
面部计数:使用时的最大面部计数,
面值:新值,
}
}如果face_vals.len()=0,则为else{
//不允许0边骰子
掷骰子{
人脸计数:1,
面_值:vec![1],
}
}否则{
//正常范围
掷骰子{
face_count:face_vals.len(),
面值:面值,
}
}
}
}
您应该使用结果来解释可能的错误输入:
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)
}
)
}
}
}
使用std::cmp::排序;
#[派生(克隆、复制)]
发布枚举类型{
D2,
D4,
D6,
D8,
D10,
D10P,
D12,
D20
}
pub结构骰子{
骰子类型:骰子类型,
//不需要脸计数,这是一种骰子类型的方法
面值:Vec
}
//无效面值输入的错误
枚举骰子错误{
TooFewFaceValues,
TooManyFaceValues
}
简单骰子类型{
fn面部计数(&self)->使用{
匹配自我{
DiceType::D2=>2,
DiceType::D4=>4,
_=>未实现!()//TODO:说明所有其他变体
}
}
}
插入骰子{
fn新(骰子类型:骰子类型,面值:&[u32])->结果{
匹配面\u值.len().cmp(&dice\u type.face\u count()){
排序::Less=>Err(DiceError::ToofeFaceValues),
排序::更大=>Err(DiceError::TooManyFaceValues),
排序::相等=>Ok(
掷骰子{
骰子型,
面_值:Vec::from(面_值)
}
)
}
}
}
您应该使用结果来解释可能的错误输入:
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)
}
)
}
}
}
使用std::cmp::排序;
#[派生(克隆、复制)]
发布枚举类型{
D2,
D4,
D6,
D8,
D10,
D10P,
D12,
D20
}
pub结构骰子{
骰子类型:骰子类型,
//不需要脸计数,这是一种骰子类型的方法
面值:Vec
}
//无效面值输入的错误
枚举骰子错误{
TooFewFaceValues,
TooManyFaceValues
}
简单骰子类型{
fn面部计数(&self)->使用{
匹配自我{
DiceType::D2=>2,
DiceType::D4=>4,
_=>未实现!()//TODO:说明所有其他变体
}
}
}
插入骰子{
fn新(骰子类型:骰子类型,面值:&[u32])->结果{
匹配面\u值.len().cmp(&dice\u type.face\u count()){
排序::Less=>Err(DiceError::ToofeFaceValues),
排序::更大=>Err(DiceError::TooManyFaceValues),
排序::相等=>Ok(
掷骰子{
骰子型,
面_值:Vec::from(面_值)
}
)
}
}
}
您应该使用具有固定长度对应数组的变体的枚举:
#[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]));
}
应使用具有固定长度对应数组的变体的枚举:
#[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]));
}
也许将骰子包装成一个结果,这样我就可以返回有效的骰子或错误?注意,您不需要retval变量。只要把if
/else
的东西放进去:if我的{Dice{…}else{Dice{…}
请不要在你的问题里放答案。欢迎您回答下面的问题,甚至接受这个答案。这更好,因为它允许社区对其他答案和这些答案进行投票。也许可以将骰子包装在结果中,以便我可以返回有效的骰子或错误?请注意,您不需要retval变量。只要把if
/else
的东西放进去:if我的{Dice{…}else{Dice{…}
请不要在你的问题里放答案。欢迎您回答下面的问题,甚至接受这个答案。这是更好的,因为它允许更多的答案和那些答案由社区投票。其想法是用户应该能够为脸提供自定义值。所以我想要一个有“[1,20,40,60]”的d4,它应该能够支持这个。您的代码会给出“[1,2,3,4]”。我会将错误更改为类似于struct DiceError{expected:usize,actual:usize}
这样的想法是用户应该能够为面提供自定义值。所以我想要一个有“[1,20,40,60]”的d4,它应该能够支持这个。您的代码将给出“[1,2,3,4]”。我会将错误更改为类似于struct DiceError{expected:usize,actual:usize}
N