Rust可迭代類型迭代器正確創(chuàng)建自定義可迭代類型的方法
在 Rust 中, for 語句的執(zhí)行依賴于類型對(duì)于 IntoIterator 的實(shí)現(xiàn), 如果某類型實(shí)現(xiàn)了這個(gè) trait, 那么它就可以直接使用 for 進(jìn)行循環(huán).
直接實(shí)現(xiàn)
在 Rust 中, 如果一個(gè)類型實(shí)現(xiàn)了 Iterator, 那么它會(huì)被同時(shí)實(shí)現(xiàn) IntoIterator, 具體邏輯是返回自身, 因?yàn)樽陨砭褪堑?
但是如果自身就是迭代器的話, 就意味著自身必須存儲(chǔ)迭代狀態(tài), 例如當(dāng)前迭代的位置. 如果是這樣的話, 迭代器就只能被使用一次. 況且自身直接被傳入 into_iter 方法后, 所有權(quán)被轉(zhuǎn)移, 該對(duì)象就無法被再次使用了.
定義類型本身:
struct IntRange {
current: i32,
step: i32,
end: i32
}直接為其實(shí)現(xiàn)迭代器:
impl Iterator for IntRange {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if self.current == self.end {
return None;
} else {
let current = self.current;
self.current += self.step;
return Some(current);
}
}
}使用該類型:
let range = IntRange { current: 0, step: 1, end: 10 };
for value in range {
println!("v: {}", value);
}所以結(jié)論是, 如果你的類型是一次性用品, 你可以直接對(duì)其實(shí)現(xiàn) Iterator
手動(dòng)實(shí)現(xiàn)迭代器
如果你向手動(dòng)實(shí)現(xiàn)類似于容器的東西, 那么它當(dāng)然不是一次性的. 我們應(yīng)該仿照 Rust 中對(duì)切片的迭代器實(shí)現(xiàn).
同時(shí)實(shí)現(xiàn)會(huì)轉(zhuǎn)移所有權(quán)和不會(huì)轉(zhuǎn)移所有權(quán)的兩個(gè)迭代器對(duì) self 和 &self 都實(shí)現(xiàn) IntoIterator, 這樣就可以做不轉(zhuǎn)移所有權(quán)的迭代了
類型本身:
struct IntRange {
step: i32,
end: i32
}兩個(gè)迭代器:
struct IntRangeIter<'a> {
range: &'a IntRange,
current: i32,
}
struct IntRangeIntoIter {
range: IntRange,
current: i32,
}兩個(gè)迭代器實(shí)現(xiàn):
impl Iterator for IntRangeIter<'_> {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if self.current == self.range.end {
return None;
} else {
let current = self.current;
self.current += self.range.step;
return Some(current);
}
}
}
impl Iterator for IntRangeIntoIter {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if self.current == self.range.end {
return None;
} else {
let current = self.current;
self.current += self.range.step;
return Some(current);
}
}
}實(shí)現(xiàn)返回兩種迭代器的 IntoIterator:
impl<'a> IntoIterator for &'a IntRange {
type Item = i32;
type IntoIter = IntRangeIter<'a>;
fn into_iter(self) -> Self::IntoIter {
IntRangeIter {
range: self,
current: 0
}
}
}
impl IntoIterator for IntRange {
type Item = i32;
type IntoIter = IntRangeIntoIter;
fn into_iter(self) -> Self::IntoIter {
IntRangeIntoIter {
range: self,
current: 0
}
}
}使用它:
let range = IntRange { step: 1, end: 10 };
// 可以使用引用來進(jìn)行 for 循環(huán)
for value in &range {
println!("v: {}", value);
}
// 也可以直接對(duì)其進(jìn)行 for 循環(huán)
for value in range {
println!("v: {}", value);
}切片對(duì)迭代的實(shí)現(xiàn)
我們知道, Rust 的切片有一個(gè) iter 方法, 其實(shí)它就相當(dāng)于對(duì)當(dāng)前切片的引用調(diào)用 into_iter.
其實(shí), 在調(diào)用切片引用的 into_iter 方法時(shí), 本質(zhì)上就是調(diào)用的其 iter 方法. 方法的實(shí)現(xiàn)是在 iter 內(nèi)的.
let v = vec![1, 2, 3]; // 下面兩個(gè)調(diào)用是等價(jià)的 let iter1 = v.iter(); let iter2 = (&v).into_iter();
如果你希望實(shí)現(xiàn)迭代變量可變的迭代器, 還可以為 &mut T 實(shí)現(xiàn) into_iter, 當(dāng)然, Rust 內(nèi)部對(duì)于切片的實(shí)現(xiàn), 也是這樣的:
let mut v = vec![1, 2, 3]; // 下面兩個(gè)調(diào)用是等價(jià)的 let mutIter = v.iter_mut(); let mutIter = (&mut v).into_iter();
總結(jié)
兩種類型:
- 對(duì)于一次性使用的類型, 可以直接對(duì)其實(shí)現(xiàn)迭代器 trait.
- 對(duì)于容器, 不應(yīng)該對(duì)容器本身直接實(shí)現(xiàn)迭代器, 而是應(yīng)該單獨(dú)創(chuàng)建迭代器類型, 然后對(duì)其本身實(shí)現(xiàn)
IntoIterator
為了方便用戶使用, 調(diào)用之間的實(shí)現(xiàn)應(yīng)該是這樣:
- 實(shí)現(xiàn)
T的IntoIterator - 實(shí)現(xiàn)
&T的iter函數(shù), 返回借用的迭代器. - 實(shí)訓(xùn)
&mut T的iter_mut函數(shù), 返回可變借用的迭代器. - 對(duì)
&T和&mut T實(shí)現(xiàn)into_iter函數(shù), 并在內(nèi)部調(diào)用剛剛實(shí)現(xiàn)的iter和iter_mut函數(shù).
這樣, 用戶就可以直接調(diào)用 iter 方法獲得借用的迭代器, 然后使用 map, filter 等方法進(jìn)行集合的復(fù)雜操作了
到此這篇關(guān)于Rust可迭代類型迭代器正確創(chuàng)建自定義可迭代類型的方法的文章就介紹到這了,更多相關(guān)Rust迭代器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
rust中間件actix_web在項(xiàng)目中的使用實(shí)戰(zhàn)
這篇文章主要介紹了rust中間件在項(xiàng)目中的使用實(shí)戰(zhàn),包括自定義中間件,日志中間件,Default?headers,用戶會(huì)話,錯(cuò)誤處理的用法實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
Rust生成隨機(jī)數(shù)的項(xiàng)目實(shí)踐
Rust標(biāo)準(zhǔn)庫(kù)中并沒有隨機(jī)數(shù)生成器,常見的解決方案是使用rand包,本文主要介紹了Rust生成隨機(jī)數(shù)的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03
rust標(biāo)準(zhǔn)庫(kù)std::env環(huán)境相關(guān)的常量
在本章節(jié)中, 我們探討了Rust處理命令行參數(shù)的常見的兩種方式和處理環(huán)境變量的兩種常見方式, 拋開Rust的語法, 實(shí)際上在命令行參數(shù)的處理方式上, 與其它語言大同小異, 可能影響我們習(xí)慣的也就只剩下語法,本文介紹rust標(biāo)準(zhǔn)庫(kù)std::env的相關(guān)知識(shí),感興趣的朋友一起看看吧2024-03-03
Rust中non_exhaustive的enum使用確保程序健壯性
這篇文章主要為大家介紹了Rust中non_exhaustive的enum使用確保程序健壯性示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11

