gpt4 book ai didi

iterator - 如何从函数返回迭代器并使用它?

转载 作者:行者123 更新时间:2023-11-29 08:14:35 28 4
gpt4 key购买 nike

我正在尝试通过一个小日历项目自学 Rust。

在这里,我试图生成一个跨越给定日期前后整整三个月的日期列表。我想返回一个可以迭代这些日期的迭代器。这是我的第一次尝试:

fn three_months_range(tm: time::Tm) -> std::iter::Iterator<Item=time::Tm> {
let fpm: time::Tm = first_of_previous_month(&tm);
(0..)
.map(|i| fpm + time::Duration::days(i))
.take_while(|&t| t.tm_mon != (tm.tm_mon + 2) % 12)
}

不幸的是,这没有编译,我得到了一个错误。

src/main.rs:49:40: 49:75 error: the trait `core::marker::Sized` is not implemented for the type `core::iter::Iterator<Item=time::Tm> + 'static` [E0277]
src/main.rs:49 fn three_months_range(tm: time::Tm) -> std::iter::Iterator <Item=time::Tm> {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:49:40: 49:75 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:49:40: 49:75 note: `core::iter::Iterator<Item=time::Tm> + 'static` does not have a constant size known at compile-time
src/main.rs:49:40: 49:75 note: the return type of a function must have a statically known size

“函数的返回类型必须具有静态已知大小”。好的,经过一番研究,似乎解决方案是通过一个 Box 返回迭代器。(仍然,我想知道标准库 mapfiltertake_while... 方法如何设法返回迭代器而不是框) .

好吧,这是第二次尝试,编译成功:

fn three_months_range(tm: time::Tm) -> Box<iter::Iterator<Item=time::Tm>> {
let fpm: time::Tm = first_of_previous_month(&tm);
Box::new(
(0..)
.map(move |i| fpm + time::Duration::days(i))
.take_while(move |&t| t.tm_mon != (tm.tm_mon + 2) % 12)
)
}

不幸的是,我没有设法使用这个迭代器。例如,假设我想构建一个向量,其中包含每个日期 (1, 2, 3, ..., 31, 1, 2, ..., 30, 1, 2, ... 31):

let days_vec: Vec<u64> = 
( *three_months_range(time::now_utc()) )
.map( |&t: &time::Tm| t.tm_mday )
.collect();

src/main.rs:14:10: 14:42 error: the trait `core::marker::Sized` is not implemented for the type `core::iter::Iterator<Item=time::Tm> + 'static` [E0277]
src/main.rs:14 .map( |&t: &time::Tm| t.tm_mday )
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:14:10: 14:42 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:14:10: 14:42 note: `core::iter::Iterator<Item=time::Tm> + 'static` does not have a constant size known at compile-time
src/main.rs:15:10: 15:19 error: no method named `collect` found for type `core::iter::Map<core::iter::Iterator<Item=time::Tm> + 'static, [closure@src/main.rs:14:15: 14:40]>` in the current scope
src/main.rs:15 .collect();
^~~~~~~~~
src/main.rs:15:10: 15:19 note: the method `collect` exists but the following trait bounds were not satisfied: `core::iter::Iterator<Item=time::Tm> : core::marker::Sized`, `[closure@src/main.rs:14:15: 14:40] : core::ops::FnMut<(time::Tm,)>`, `core::iter::Map<core::iter::Iterator<Item=time::Tm> + 'static, [closure@src/main.rs:14:15: 14:40]> : core::iter::Iterator`
src/main.rs:14:10: 14:42 error: type mismatch: the type `[closure@src/main.rs:14:15: 14:40]` implements the trait `for<'r> core::ops::FnMut<(&'r time::Tm,)>`, but the trait `core::ops::FnMut<(time::Tm,)>` is required (expected struct `time::Tm`, found &-ptr) [E0281]
src/main.rs:14 .map( |&t: &time::Tm| t.tm_mday )
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:14:10: 14:42 help: run `rustc --explain E0281` to see a detailed explanation
src/main.rs:14:10: 14:42 error: type mismatch: the type `[closure@src/main.rs:14:15: 14:40]` implements the trait `for<'r> core::ops::FnOnce<(&'r time::Tm,)>`, but the trait `core::ops::FnOnce<(time::Tm,)>` is required (expected struct `time::Tm`, found &-ptr) [E0281]
src/main.rs:14 .map( |&t: &time::Tm| t.tm_mday )
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:14:10: 14:42 help: run `rustc --explain E0281` to see a detailed explanation
error: aborting due to 4 previous errors

那是很多错误。

那么我做错了什么?

有没有一种相对简单的方法来转换 Rust 中的迭代器和/或从函数中返回它们?

最佳答案

问题是您正试图将 IteratorBox 中取出(您不能这样做,因为它是一个特征对象,因此不是 尺寸)。但是 Box 是透明的,你可以直接在上面使用 map :

let days_vec: Vec<u64> = 
three_months_range(time::now_utc())
.map( |&t: &time::Tm| t.tm_mday )
.collect();

请注意,map 函数希望您按值而不是按引用获取参数。所以调用看起来像这样:

.map(|t| t.tm_mday)

关于iterator - 如何从函数返回迭代器并使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36385557/

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