gpt4 book ai didi

rust - 我如何每晚在 Rust 1.25 中正确实现 std::iter::Step?

转载 作者:行者123 更新时间:2023-11-29 07:55:33 28 4
gpt4 key购买 nike

我正在尝试实现一个结构来表示日期,它可以与范围语法一起使用(for d in start..end { })。我知道那里已经有处理日期的 crate ,但我这样做是为了练习。

结构如下:

type DayOfMonth = u8;
type Month = u8;
type Year = u16;

#[derive(PartialEq, Eq, Clone)]
pub struct Date {
pub year: Year,
pub month: Month,
pub day: DayOfMonth
}

下面是我想如何使用它:

fn print_dates() {
let start = Date { year: 1999, month: 1, day: 1 };
let end = Date { year: 1999, month: 12, day: 31 };

for d in start..end {
println!("{}-{}-{}", d.year, d.month, d.day);
}
}

我最初尝试实现 Iterator 特性,但是当我尝试使用范围语法时,出现编译器错误,提示我需要实现 Step

文档显示了 Step 特征的这个签名。

pub trait Step: PartialOrd<Self> + Clone {
fn steps_between(start: &Self, end: &Self) -> Option<usize>;
fn replace_one(&mut self) -> Self;
fn replace_zero(&mut self) -> Self;
fn add_one(&self) -> Self;
fn sub_one(&self) -> Self;
fn add_usize(&self, n: usize) -> Option<Self>;
}

我已经实现了 OrdPartialOrd:

impl Ord for Date {
fn cmp(&self, other: &Self) -> Ordering {
match self.year.cmp(&other.year) {
Ordering::Equal =>
match self.month.cmp(&other.month) {
Ordering::Equal =>
self.day.cmp(&other.day),
ord => ord
},
ord => ord
}
}
}

impl PartialOrd for Date {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

我正在使用 #[derive(Clone)] 自动实现 Clone

我开始实现 Step,但有些方法我不知道该用什么。这是我到目前为止所拥有的:

impl Step for Date {
fn steps_between(start: &self, end: &self) -> Option<usize> {
//is_valid_date checks that the month is not > 12 and other rules like that
if is_valid_date(start) && is_valid_date(end) {
//get_epoch_day_number gets the number of days since 1900-01-01
let diff = get_epoch_day_number(end) - get_epoch_day_number(start);
Some(diff)
}
else { None }
}

fn add_one(&self) -> Self {
//Try the next day
let mut next = Date {
year: self.year,
month: self.month,
day: self.day + 1
};
//If not valid, try the 1st of the next month
if !is_valid_date(&next) {
next = Date {
year: self.year,
month: self.month + 1,
day: 1
};
}
//If not valid, try the 1st of the next year
if !is_valid_date(&next) {
next = Date {
year: self.year + 1,
month: 1,
day: 1
};
}
next
}

fn sub_one(&self) -> Self {
//Try the prev day
let mut prev = Date {
year: self.year,
month: self.month,
day: self.day - 1
};
//If not valid, try the last of the prev month
if !is_valid_date(&prev) {
let m = self.month - 1;
prev = Date {
year: self.year,
month: m,
day: get_month_length(self.year, m)
};
}
//If not valid, try the last of the prev year
if !is_valid_date(&prev) {
prev = Date {
year: self.year - 1,
month: 12,
day: 31
};
}
prev
}

fn add_usize(&self, n: usize) -> Self {
//This is really inefficient, but that's not important
let mut result = self;
for i in 1..n+1 {
result = result.add_one();
}
result
}

fn replace_one(&mut self) -> Self {
// ?
}

fn replace_zero(&mut self) -> Self {
// ?
}
}

我真的对 replace_onereplace_zero 应该做什么感到困惑。文档说:

将此步骤替换为 1,返回自身。 并且将此步骤替换为 0,返回自身。

我的结构是否需要有 01 标识值才能在一个范围内使用? add_one 应该不够吗?

文档使用的措辞也有点不清楚。如果我们将 x 替换为 1 并返回“自身”,那么“它”是 x 还是 1

最佳答案

我刚刚查看了使用这些方法的 Rust 代码。 The only uses in whole of rustc's repository是实现 RangeInclusive 操作。空的 RangeInclusive 表示为从 10 的范围,因此 nextnext_backnth 方法需要能够以某种方式获取它们,这就是 replace_onereplace_zero 的用途。

我建议在 rustc 的 GitHub 上提出一个问题以改进文档,并可能更改这些方法的名称。

关于rust - 我如何每晚在 Rust 1.25 中正确实现 std::iter::Step?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48613484/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com