Anuncios

Bienvenidos sean a este post, hoy hablaremos sobre un tipo particular de dato.

Anuncios
Anuncios

Este tipo de dato tiene la caracteristica de no tener propiedad (ownership), a su vez nos permite hacer una referencia a una secuencia contigua de elementos en una coleccion en lugar de la coleccion completa, esto nos puede resultar para ciertas practicas, para entenderlo un poco mejor vamos a suponer que necesitamos una funcion que nos devuelva la primera palabra de un texto, para ello debemos crear un nuevo proyecto que llamaremos slices, una vez creado modificaremos el codigo generado en el archivo main.rs de la siguiente manera:

main.rs

fn primer_palabra(s: &String) -> usize
{
	let b = s.as_bytes();

	for (i, &item) in b.iter().enumerate()
	{
		if item == b' '
		{
			return i;
		}
	}

	s.len()
}

fn main() 
{
	let s = String::from("Hola mundo!");
	let palabra = primer_palabra(&s);
	s.clear();
}
Anuncios
Anuncios

Para ello primero definiremos una funcion que se llamara primer_palabra, estara un argumento de tipo String pero devolvera un valor de tipo usize, este es un apuntador definido de tipo entero sin signo, dentro del bloque primero definiremos una nueva variable que tendra la cadena pasada como argumento pero en bytes, despues por medio de un bucle for iremos almacenando dos variables, una para el valor de la vuelta y otra para el elemento (item) de la posicion, para ello tomaremos la variable definida anteriormente y la convertiremos en un iterador y la enumeraremos para poder ser accedida como tal, en este bucle chequearemos si item es igual al valor en bytes del espacio en blanco si esto es verdad devolveremos el valor actual de i, el cual encaja con el tipo que devolvemos en la funcion, pero suponiendo que no exista ningun espacio, es decir que es toda una palabra, devolveremos el tamaño total del argumento, nuestro siguiente paso sera en el main y definiremos una nueva variable que almacenara una cadena, despues en otra variable almacenaremos el valor devuelto por la funcion, por ultimo limpiamos a la primera variable que definimos, si lo compilamos y probamos funcionara pero no hara nada, si mostraramos el valor que devuelve la funcion seria simplemente la ubicacion de nuestro primer espacio en blanco, para transformarlo en un codigo eficiente lo debemos modificar de la siguiente manera:

main.rs

fn primer_palabra(s: &String) -> usize
{
	let b = s.as_bytes();

	for (i, &item) in b.iter().enumerate()
	{
		if item == b' '
		{
			return i;
		}
	}

	s.len()
}

fn main() 
{
	let s = String::from("Hola mundo!");
	let pos = primer_palabra(&s);
	let palabra = &s[0..pos];
	println!("{}", palabra);
}
Anuncios

La funcion se mantiene eactamennte igual pero las modificaciones les hicimos en el main, seguimos creando nuestra variable con una cadena, luego le cambiamos el nombre a la variable palabra por pos y en esta almacenaremos el valor devuelto por la funcion, luego definimos a la variable palabra y en ella usaremos un tipo especial de slice, string slice, el cual fue mencionado en este post.

Anuncios

Este tipo de slice es para los tipos String donde le diremos desde que posicion a que posicion debemos extraer la porcion de informacion de la variable, su sintaxis es como la ven en el codigo, como sabemos que es la primera palabra la que deseamos obtener le indicamos la posicion 0 como inicial y la final sera la obtenida por la funcion, por ultimo lo mostraremos en pantalla, compilemos y veamos su salida:

tinchicus@dbn001vrt:~/lenguajes/rust/slices$ cargo run
   Compiling slices v0.1.0 (/home/tinchicus/lenguajes/rust/slices)
    Finished dev [unoptimized + debuginfo] target(s) in 1.03s
     Running `target/debug/slices`
Hola
tinchicus@dbn001vrt:~/lenguajes/rust/slices$
Anuncios

Aunque esto no aplica unicamente al tipo string sino tambien a los demas tipos por lo tanto si tenemos el siguiente vector:

let v = vec![1, 2, 3, 4, 5];
Anuncios

Para aplicarle un slice a este vector lo podemos hacer de la siguiente manera:

let slice = &v[1..3];
Anuncios

Esto nos deberia devolver los valores del 2 al 4, pero el codigo anterior lo podemos mejorar y para ello debemos modificar el codigo anterior de la siguiente manera:

main.rs

fn primer_palabra(s: &String) -> &str
{
	let b = s.as_bytes();

	for (i, &item) in b.iter().enumerate()
	{
		if item == b' '
		{
			return &s[0..i];
		}
	}

	return s;
}

fn main() 
{
	let s = String::from("Hola mundo!");
	println!("{}", primer_palabra(&s));
}
Anuncios
Anuncios

Aqui primero cambiamos la funcion donde en lugar de devolver un valor de tipo entero devolvera un string, despues trabaja de la misma forma pero ahora en el condicional donde busca el espacio en blanco y en lugar de devolver el valor de la posicion devolveremos el string slice de la cadena que usamos como argumento, y en lugar de devolver el tamaño del argumento devolveremos a este en caso de no cumplirse la condicion anterior, por ultimo en el main seguiremos definiendo una variable con una cadena para luego solo mostrar el resultado que devuelve nuestra funcion, si lo compilan deberan obtener la misma salida que anteriormente, es decir que inclusive lo podemos usar como resultado de devolucion de una funcion, por ultimo las cadenas literales tambien son consideradas como slices.

Anuncios

En resumen, hoy hemos visto a slice, que es, como se compone, como lo podemos utilizar, hemos visto un par de ejemplos donde primero lo vemos en accion de manera simple, para luego mejorarlo, tambien hemos visto otros tipos de slice, espero les haya sido de utilidad 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.

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50