![](/img/trans.png)
[英]How to convert IntoIterator<Item=AsRef<str>> to Iterator<Item=&str> in Rust?
[英]Getting an Iterator<Item=str> from an array of &str?
我正在嘗試抽象一個 function 以獲取std::str::Lines
的實例和用於測試目的的模擬版本,從&str
的數組創建。
我的代碼(確實有效)看起來像這樣:
use std::fs;
#[test]
fn test_day_1() {
let v = ["3", "3", "4", "-2", "-4"].iter().map(|x| *x);
assert_eq!(day1(v), "334-2-4334-2-4");
}
fn day1_pre() -> String {
let contents = fs::read_to_string("day1.txt").expect("error reading file");
day1(contents.lines())
}
fn day1<'a>(lines: impl Iterator<Item = &'a str> + Clone) -> String {
lines
.map(|line| {
let v: Result<i32, _> = line.parse();
v.expect("could not parse line as integer")
})
.cycle()
.take(10)
.map(|x| x.to_string())
.collect()
}
但是,由於測試中存在奇怪的.map(|x| *x)
,此代碼才有效。 如果我刪除它,我會收到以下錯誤:
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, &str> as Iterator>::Item == &str`
--> src/lib.rs:6:16
|
6 | assert_eq!(day1(v), "334-2-4334-2-4");
| ^^^^ expected `str`, found `&str`
...
14 | fn day1<'a>(lines: impl Iterator<Item = &'a str> + Clone) -> String {
| -------------- required by this bound in `day1`
|
= note: expected reference `&str`
found reference `&&str`
我有點理解這個錯誤。 iter
返回一個&T
,在本例中它產生一個&&str
。 我不明白的是為什么要刪除map
並將iter
替換為into_iter
(即let v = ["3", "3", "4", "-2", "-4"].into_iter();
)也因同樣的錯誤而失敗!
根據文檔, into_iter
迭代T
,因此它應該在這里工作?
在寫這篇文章時,我還嘗試用Vec
替換數組並使用into_iter
,這樣最終的結果是let v = vec,["3","3","4","-2"."-4"];into_iter();
它奏效了,但是,現在我更加困惑了,為什么into_iter
對Vec
有效但對Array
無效?
這是在Rust 1.53 發行說明中公布的。 IntoIterator
for arrays 是在 1.53 中實現的新增功能,但在 2018 和 2021 版本中表現不同:
由於向后兼容性問題,這在以前沒有實現。 因為
IntoIterator
已經實現了對 arrays 的引用,所以array.into_iter()
已經在早期版本中編譯,解析為(&array).into_iter()
。
截至此版本,arrays 實施 IntoIterator 並使用一個小的解決方法來避免破壞代碼。 編譯器將繼續將
array.into_iter()
解析為(&array).into_iter()
,就好像特征實現不存在一樣。 這僅適用於.into_iter()
方法調用語法,不會影響任何其他語法,例如for e in [1, 2, 3]
、iter.zip([1, 2, 3])
或IntoIterator::into_iter([1, 2, 3])
,它們都可以正常編譯。
由於
.into_iter()
的這種特殊情況只是為了避免破壞現有代碼,因此在今年晚些時候發布的新版本 Rust 2021 中將其刪除。 有關詳細信息,請參閱版本公告。
因此,您的代碼將在 Rust 2021 下正常編譯
在這種情況下,您可以將任何可以作為引用的內容的迭代器帶入 str (任何&&&&&..&str
應該):
fn day1<T>(lines: impl Iterator<Item = T> + Clone) -> String where T : AsRef<str>{
lines
.map(|line| {
let v: Result<i32, _> = line.as_ref().parse();
v.expect("could not parse line as integer")
})
.cycle()
.take(10)
.map(|x| x.to_string())
.collect()
}
為什么into_iter
對Vec
而不是切片起作用,好吧,如果您在使用into_iter
時閱讀當前警告:
warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
--> src/lib.rs:5:41
|
5 | let v = ["3", "3", "4", "-2", "-4"].into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= note: `#[warn(array_into_iter)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
按照有很好解釋的問題鏈接進行操作。 要點是:
[1, 2, 3].into_iter().for_each(|n| { *n; });
目前這是可行的,因為 into_iter 返回對數組值的引用的迭代器,這意味着 n 確實是 &{integer} 並且可以取消引用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.