[英]Rust: how to return an iterator from a function and use it?
我正在嘗試通過一個小日歷項目來教自己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返回迭代器。 (仍然,我想知道標准庫map
, filter
, take_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中的迭代器和/或從函數返回它們?
問題是你試圖將Iterator
從Box
取出(你不能因為它是一個特征對象,因此不是Sized
)。 但是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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.