Los genéricos con aritmética de enteros muestran “se esperaba el parámetro de tipo T, se encontró integer”.
Intento escribir una función genérica en Rust donde realice un cálculo aritmético. Desafortunadamente, el compilador no permite mezclar T con un entero. La primera función evens no genérica funciona, mientras que la segunda no se compila.
use itertools::Itertools;
use num::Integer;
pub fn evens(iter: impl Iterator<item =="" i32="">) -> impl Iterator<item =="" i32=""> {
iter.filter(|x| *x % 2 == 0)
}
pub fn evens_generic<t: integer="">(iter: impl Iterator<item =="" t="">) -> impl Iterator<item =="" t=""> {
iter.filter(|x| *x % 2 == 0)
}
fn main() {
let nums = vec!(1, 2, 3, 4, 5);
let filtered = evens_generic(nums.into_iter());
println!("{}", filtered.format(" "));
}
Obtengo el error del compilador:
error[E0308]: tipos no coinciden
--> src/main.rs:9:26
|
8 | pub fn evens_generic<t: integer="">(iter: impl Iterator<item =="" t="">) -> impl Iterator<item =="" t=""> {
| - este parámetro de tipo
9 | iter.filter(|x| *x % 2 == 0)
| ^ se esperaba el parámetro de tipo `T`, se encontró un entero
|
= nota: se esperaba el parámetro de tipo `T`
se encontró el tipo `{integer}`
Entiendo que los traits que agrego solo limitarán a los tipos que implementan ciertas funciones y no al tipo en sí. Pero hubiera esperado que, al limitarlo a Integer, pudiera convertir el parámetro de la función del módulo al tipo T.
davy.ai
El problema con la función
evens_generic
es que el operador de módulo%
no está implementado para todos los tipos que implementan el rasgoInteger
. Específicamente, el operador de módulo requiere que ambos operandos sean del mismo tipo, y en este caso, un operando es de tipoT
(el parámetro de tipo genérico) y el otro es de tipoi32
(el literal entero 2).Para solucionar esto, necesitamos asegurarnos de que ambos operandos del operador de módulo sean del mismo tipo. Una forma de hacer esto es utilizar el rasgo
num::cast::AsPrimitive
para convertir el literal entero 2 al tipoT
. Aquí está la funciónevens_generic
modificada:En esta versión de
evens_generic
, hemos agregado dos rasgos adicionales al parámetro de tipo genéricoT
:NumCast
yCopy
.NumCast
es necesario para convertir el literal entero 2 al tipoT
, yCopy
es necesario porque usamos el métodocopied()
en el iterador para evitar problemas de tiempo de vida.Dentro del cierre
filter
, primero convertimos el literal entero 2 al tipoT
usandoT::from(2).unwrap()
. Luego utilizamos el rasgoAsPrimitive
para convertir el resultado deT::from(2).unwrap()
al mismo tipo quex
usando el métodoas_()
. Finalmente, podemos utilizar el operador de módulo%
con dos operandos del mismo tipo para filtrar los números pares.Con estas modificaciones, la función
evens_generic
debería funcionar ahora con cualquier tipo que implemente los rasgos necesarios.