Bienvenidos sean a este post, hoy hablaremos sobre como solucionar el tema del post anterior.
Mas adelante hablaremos sobre los trait pero hoy hablaremos sobre uno de ellos como es el copy trait, si bien nosotros mencionamos en el post anterior que una conducta de Rust es que dos objetos no pueden estar unidos a un valor almacenado en memoria, esto es una verdad a medias dado que en tipos primitivos como pueden ser int, float o char el lenguaje aplica el copy trait, por lo tanto si trabajamos con tipos primitivos solamente este problema no sucedera porque al momento de cambiar la propiedad en realidad el lenguaje hara una copia de este en lugar de asignarlo por lo tanto cada variable estara unida a valores similares pero no en la misma ubicacion de memoria por lo tanto funcionara correctamente pero que sucede con los no primitivos, como por ejemplo Vector? En este caso si fallara porque no utiliza este trait, recuerdan el codigo del post anterior donde nos indicaba que Vector no trabaja con Copy trait, pero esto podemos solucionarlo, para ello debemos crear dos nuevos proyectos para verlos en accion.
Primero vamos a crear un proyecto al cual llamaremos copiari32, una vez creado modificaremos el codigo generado automaticamente de main.rs de la siguiente manera:
main.rs
fn incrementar(n: i32) -> i32
{
n + 32
}
fn main()
{
let num = 10i32;
let num2 = incrementar(num);
println!("num es: {}", num);
println!("num2 es: {}", num2);
}
Este es el primero ejemplo para mostrar lo que comentamos, es decir que los tipos primitivos hacen de forma automatica el copy trait, comencemos a analizar el codigo y para ello primero tenemos una funcion que recibe un valor lo incrementa y lo devuelve, en el post anterior mencionamos que la transferencia podia afectar inclusive cuando pasamos una variable a una funcion, luego tenemos la funcion main donde crearemos dos variables, la primera (num) definida con un valor, la segunda (num2) almacenara el valor que devuelve la funcion incrementar y le pasamos el valor de la variable anterior, por ultimo mostramos ambos valores, compilemos y veamos su salida:
tinchicus@dbn001vrt:~/lenguajes/rust/copiari32$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target/debug/copiari32`
num es: 10
num2 es: 42
tinchicus@dbn001vrt:~/lenguajes/rust/copiari32$
Como pueden ver funciono perfecto tal como mencionamos gracias al copy trait, ahora vamos a ver lo mismo pero con vectores, para ello crearemos un nuevo proyecto que llamaremos copiar, una vez generado, modificaremos el codigo creado de main.rs con el siguiente:
main.rs
fn sumar(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32)
{
let sum = v1.iter().fold(0i32, |a, &b| a + b);
let prod = v2.iter().fold(1i32, |a, &b| a * b);
return (v1, v2, sum + prod);
}
fn main()
{
let vecuno = vec![2, 3, 5];
let vecdos = vec![3, 5];
let(vecuno, vecdos, rta) = sumar(vecuno, vecdos);
println!("{}", vecuno[0]);
println!("{}", vecdos[0]);
println!("{}",rta);
}
Analicemos primero la funcion sumar, en este caso recibira dos valores de tipo vector y en esta funcion devolveremos no solamente los dos tipos que recibimos sino tambien uno de tipo i32, luego tenemos dos variables que usaremos para procesar cada uno de los argumentos que recibimos, el primero se llamara sum y trabajara con el primer argumento (v1), para ello usaremos al metodo fold de la interface iter, una interfaz para hacer iteraciones, de manera breve este metodo se encarga de almacenar un elemento dentro de un acumulador aplicandole una operacion, para finalmente devolver el resultado final, esta se compone de dos valores, un valor inicial y un cierre con dos argumentos: un ‘acumulador’ y un elemento, el cierre devuelve el valor que debería tener el acumulador para la siguiente iteración, en este caso lo primero que haremos sera el incremento de la suma entre los distintos valores que posee el vector, la siguiente variable es exactamente lo mismo pero para el segundo argumento y en lugar de sumar lo multiplica, por ultimo devolvemos los dos argumentos y la suma entre las dos iteraciones, lo cual encaja con el formato de como devolvemos los datos.
Lo siguiente sera la funcion main, donde aqui crearemos dos variables con vectores con sus respectivos valores, luego crearemos un tuple donde aplicaremos la funcion anterior, observen que recibira tres valores, y a la funcion le pasamos las variables antes creadas, por ultimo le diremos que muestre a posicion 0 de cada uno de los vectores y lo que seria el producto de la suma de las dos iteraciones que hicimos en la funcion, con esto comentado podemos pasar a compilarlo y ver su salida:
tinchicus@dbn001vrt:~/lenguajes/rust/copiar$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/copiar`
2
3
25
tinchicus@dbn001vrt:~/lenguajes/rust/copiar$
Como pueden ver funciono a pesar de que transferimos los vectores y obviamente cambiamos la union de estas propiedades pero el que hace la magia es esta linea:
return (v1, v2, sum + prod);
Dado que basicamente estas volviendo a asignar las uniones que se transfirieron anteriormente, si bien esto es muy tosco nos permite trabajar sin que se nos genere ningun error pero no es el unico que existe pero de eso hablaremos en el proximo post.
En resumen, hoy hemos visto a copy trait, una forma que posee Rust para poder copiar valores en tipos primitivos y nos permite poder hacer copias de valores de un objeto a otro sin vulnerar la regla que vimos en propiedades (ownership), pero esto no se aplica para tipos no primitivos por lo tanto en tipos como vector fallara, aunque vimos un ejemplo donde podemos hacer que esto no ocurra, espero les haya sido util sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
