Tôi muốn viết một hàm chấp nhận một trình lặp và trả về kết quả của một số thao tác trên nó. Cụ thể, tôi đang cố gắng để lặp qua các giá trị của một HashMap
:Làm thế nào để viết một hàm Rust có một trình lặp?
use std::collections::HashMap;
fn find_min<'a>(vals: Iterator<Item=&'a u32>) -> Option<&'a u32> {
vals.min()
}
fn main() {
let mut map = HashMap::new();
map.insert("zero", 0u32);
map.insert("one", 1u32);
println!("Min value {:?}", find_min(map.values()));
}
Nhưng than ôi:
error: the `min` method cannot be invoked on a trait object
--> src/main.rs:4:10
|
4 | vals.min()
| ^^^
error[E0277]: the trait bound `std::iter::Iterator<Item=&'a u32> + 'static: std::marker::Sized` is not satisfied
--> src/main.rs:3:17
|
3 | fn find_min<'a>(vals: Iterator<Item = &'a u32>) -> Option<&'a u32> {
| ^^^^ `std::iter::Iterator<Item=&'a u32> + 'static` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `std::iter::Iterator<Item=&'a u32> + 'static`
= note: all local variables must have a statically known size
error[E0308]: mismatched types
--> src/main.rs:11:41
|
11 | println!("Min value {:?}", find_min(map.values()));
| ^^^^^^^^^^^^ expected trait std::iter::Iterator, found struct `std::collections::hash_map::Values`
|
= note: expected type `std::iter::Iterator<Item=&u32> + 'static`
found type `std::collections::hash_map::Values<'_, &str, u32>`
tôi nhận được lỗi tương tự nếu tôi cố gắng vượt qua bằng cách tham khảo; nếu tôi sử dụng Box
, tôi sẽ gặp phải lỗi lâu dài.
Tôi đã rất thân thiết. Để giải thích, sự khác biệt với Generics là công văn tĩnh, tức là, Rust đang tạo ra một phiên bản của hàm này cho từng loại cụ thể mà tôi gọi nó là? –
Chính xác. Bằng cách này, trình biên dịch biết loại của trình lặp, do đó nó biết kích thước của nó, do đó, nó biết bao nhiêu bộ nhớ cần thiết để dự trữ. Ngoài ra, một kiểu như 'Iterator- ' không thể được sử dụng một mình; nó chỉ có thể được sử dụng sau một con trỏ. –
Lưu ý rằng trong khi yêu cầu 'I' để thực hiện' Iterator' là hoàn toàn chính xác nếu bạn muốn chuyển các trình vòng lặp tùy ý vào hàm, thì cách chung chung hơn sẽ là yêu cầu 'I' thực hiện [' IntoIterator'] (http: // doc.rust-lang.org/std/iter/trait.IntoIterator.html). Nó cho phép bạn vượt qua vòng lặp quá nhưng bạn cũng sẽ có thể chuyển bất kỳ thứ gì có thể được * chuyển đổi * thành một trình lặp, mà không cần gọi các phương thức chuyển đổi một cách rõ ràng. Tôi muốn nói đây là * cách tiếp cận thành ngữ * để sử dụng các trình vòng lặp và các vòng lặp. –