Rust程式語言融合了多種程式設計法(programming paradigm),其中的指令式程式設計(imperative programming)所用的迴圈和函數式程式設計(functional programming)所提供的迭代器(iterator)可以加強陣列或是切片的走訪效能。然而,很多時候我們並不需要直接走訪到陣列或是切片的最尾端,而是只想要在經過指定的迭代次數之後,就結束走訪,這時可以利用Rust提供的陣列轉切片或是切片再切片的功能來進行索引值範圍的限縮,事實上迭代器也有提供take
方法,可以在執行完指定的迭代次數之後,提前終止後續待走訪的元素。那如果迭代器的走訪對象是陣列或是切片時,使用take
方法會比直接使用更小範圍的切片還要慢嗎?
我們先來看看以下程式碼:
let array = [2, 2, 3, 4, 5, 6, 7, 8];
for i in 0..5 {
println!("{}", array[i]);
}
以上程式,會利用For計次迴圈來從頭開始走訪這個存在於堆疊內的陣列,並將走訪到的元素值印在螢幕上,直到走訪到索引4
的元素為止。
在先前的文章中,我們已經知道用For迴圈來走訪堆疊內的陣列,效能跟和用For迭代器迴圈或是迭代器是一樣的。
所以,以上程式其實也會等效於以下的For迭代器迴圈程式:
let array = [2, 2, 3, 4, 5, 6, 7, 8];
for &n in array[..5].iter() {
println!("{}", n);
}
以上程式,利用Rust提供的陣列轉切片功能,切片範圍只有陣列前5個元素,所以走訪這個切片,就相當於從頭開始走訪原陣列,直到索引4
的元素為止。那如果我們不使用切片,而是用迭代器提供的take
方法來完成這個在走訪陣列時指定迭代次數的功能呢?程式如下:
let array = [2, 2, 3, 4, 5, 6, 7, 8];
for &n in array.take(5) {
println!("{}", n);
}
使用take
方法所二度產生出來的迭代器,會影響到效能嗎?
效能實測
直接實際寫一段程式來測試運算效能吧!這段程式可以在GitHub上取得:
根據測試結果,可以發現使用take
方法的效能與使用切片是幾乎一樣的。這是因為take
方法所產生的Take
結構實體,只不過就是多加了一個變數來記錄其剩餘的next
方法的呼叫次數。程式如下:
fn next(&mut self) -> Option<<I as Iterator>::Item> {
if self.n != 0 {
self.n -= 1;
self.iter.next()
} else {
None
}
}
所以它對程式效能影響不大。