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