recorrer patron listas linkedlist imprimir implementar example ejemplo function iterator rust

function - patron - recorrer arraylist java foreach



¿Cómo escribir una función Rust que tome un iterador? (2)

Me gustaría escribir una función que acepte un iterador y devuelva los resultados de algunas operaciones en él. Específicamente, estoy tratando de iterar sobre los valores de un HashMap :

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())); }

Pero Ay:

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>`

Me sale el mismo error si trato de pasar por referencia; si utilizo un Box , recibo errores de por vida.


Desea utilizar los genéricos aquí:

fn find_min<''a, I>(vals: I) -> Option<&''a u32> where I: Iterator<Item = &''a u32>, { vals.min() }

Los rasgos se pueden usar de dos maneras: como límites en los parámetros de tipo y como objetos de rasgo. El libro The Rust Programming Language tiene un capítulo sobre los traits y un capítulo sobre los objetos de rasgo que explican estos dos casos de uso.

Además, a menudo desea tomar algo que implemente IntoIterator ya que esto puede hacer que el código llame mejor a su función:

fn find_min<''a, I>(vals: I) -> Option<&''a u32> where I: IntoIterator<Item = &''a u32>, { vals.into_iter().min() }


Este comportamiento es un poco intuitivo de aquellos con un fondo de Python en lugar de, por ejemplo, un fondo C ++, así que déjenme aclarar un poco.

En Rust, los valores se almacenan conceptualmente dentro del nombre que los une. Por lo tanto, si escribes

let mut x = Foo { t: 10 }; let mut y = x; x.t = 999;

y todavía será 10 .

Entonces cuando escribes

let x: Iterator<Item=&''a u32>;

(o lo mismo en la lista de parámetros de función), Rust necesita asignar suficiente espacio para cualquier valor de tipo Iterator<Item=&''a u32> . Incluso si esto fuera posible, no sería eficiente.

Entonces, lo que hace Rust es ofrecerle la opción de

  • Pon el valor en el montón, ej. con Box , que proporciona semántica al estilo de Python. Luego puede tomar genéricamente con &mut Iterator<Item=&''a u32> .

  • Especialice cada invocación de función para cada tipo posible para satisfacer el límite. Esto es más flexible, ya que una referencia de rasgo es una especialización posible, y le da al compilador más oportunidades de especialización, pero significa que no puede tener despacho dinámico (donde el tipo puede variar dependiendo de los parámetros de tiempo de ejecución).