Los lenguajes de programación distan de ser perfectos. Unos muy verbosos (Java). Otros muy complicados (Perl). Otros tantos demasiado concretos o lo que es lo mismo muy poco abstractos (C, también conocido como ASM con variables 😛 ). Unos con arrastres de sus antecesores que lastran a sus nuevas generaciones (C++, Javascript, Python [si sabes que es Gil y Slots sabes de que hablo]). Y también tenemos a PHP   😀 . Eso provoca que día a día surjan nuevos lenguajes que, si bien no están a salvo de sus propios defectos, intentan resolver los problemas de sus antecesores en al menos un nicho determinado. En este post estaremos hablándoles de uno de ellos, en este caso un engendro de Mozilla, Samsung y una gran comunidad de desarrolladores de todo el mundo: Rust.

rustacean-orig-happy.ai

Para comenzar con Rust, el hola mundo que no puede faltar, pero sin comentarios porque no creo que hagan falta:

fn main(){
println!("¡Hola Mundo!");
println!("Hello World!");
println!("Привет мир!");
println!("שלום העולם!");
println!("こんにちは世界!");
}

Rust es un lenguaje diseñado con el objetivo de cubrir la misma área de acción que C++, escribir programas grandes que requieran de velocidad. Esto con la premisa de solventar muchos de los problemas de memoria que tienen C++ algunos de ellos heredadas de C. Estos ya han sido resueltos en otros lenguajes como Java, C#, D, Go y los conocidos lenguajes de scripting (Javascript, Python, Ruby, PHP….) en todos ellos gracias al empleo de recolectores de basura, pero resulta que esta solución acarrea consigo pérdida de velocidad por el propio funcionamiento de esta técnica. Rust por su parte propone un nuevo modelo de manejo de los punteros que permite al compilador saber donde termina la vida de un objeto, de modo que inyecta el código que lo destruye, desde el tiempo de compilación y no de ejecución. Sí, suena a ciencia ficción pero no lo es.
Ya sabido esto, veamos la implementación de nuestro viejo amigo FizzBuzzBazz en Rust, esta vez sí lo comentaré, de forma que vayan conociendo algunas de la características del lenguaje, pero es solo un bocado, es probable que me embulle y aborde más del tema en otros posts.

 

fn main() {
  let msgs = vec![(3, "Fizz"), (4, "Buzz"), (5, "Bazz")];
  for i in 1..101 {
    let mut out = "".to_string();
    for &(val, msg) in &msgs{
      if i % val == 0{
      out = out + msg;
     }
    }
    if out.len() == 0 {out = format!("{:?}", i)}
    println!("{:?}", out);
  }
}

En la primera línea se crea la función main, que como en C y C++ es el punto de entrada del programa.

En la segunda línea vemos que se emplea la palabra reservada let, esta crea la variable msgs, la cual es inmutable. Esto último quiere decir que una vez inicializada su valor no cambia, esto aunque puede parecer similar a las const de C++ tiene ciertas diferencias, por ejemplo, las const solo pueden inicializarse con expresiones constantes, o sea que su valor pueda ser calculado por el compilador antes de que el programa se ejecute. Las variables inmutables no son iguales en este sentido, su valor puede ser creado en tiempo de ejecución, solo que este no puede ser modificado de ninguna forma (esto no se puede decir de las const de C++, que pueden ser modificadas usando const_cast). Esto puede resultar un poco confuso pero si recuerdas, en matemáticas cuando decías que x = 2, era 2 siempre, no podías ir por ahí incrementándola o todo perdía sentido.

En esta línea también vemos el empleo de vec!, el ! nos indica que este es un macro, que en este caso crea un vector con esos elementos. Los macros en Rust son de verdad (I put an eye on you C&C++), similares a los de Lisp, son capaces de introducir nodos en el AST sin ensuciar el contexto exterior.

Ya en la segunda linea vemos un for que al menos a mí me recuerda a CoffeeScript o Ruby y sí, hace lo mismo que en esos lenguajes.
Ya en la cuarta línea vemos el empleo de la palabra reservada mut que se usa en conjunto con let para crear una variable mutable (vaya, una variable como la de los lenguajes imperativos “clásicos”), esta sí es necesario que sea cambiable, así que se lo decimos.

En linea a continuación vemos un for que nos muestra otra de las características de Rust, la destructuración de objetos, en este caso de las tuplas que conforman al vector msgs, el empleo de & es para indicar que se quiere una referencia y no una copia del valor.
En las líneas siguientes se nota el empleo de if así como los macros format! y println! para generar una cadena a partir de una plantilla y valores; en el primer caso, en el segundo se genera la cadena y se imprime directamente.

Por la sencillez del ejemplo en cuestión no puedo mostrarles otras de las facilidades presentes en el lenguaje que me gustan mucho, tales como las capturas (que es un switch con esteroides), el borrowing (préstamo en español, esto es lo que permite manejar la memoria sin necesidad de recolector de basura), los movimientos (similares a los de C++11) y la calidad de los errores del compilador. Otras características a resaltar son Cargo que remplaza a (make, rake) y a (pip, gem, npm) para Rust. Y el hecho de que todo es una expresión (sí, los if y los for también), de nuevo como en CoffeeScript y en Ruby.

Esto es todo por hoy, espero que les haya gustado.

PD: La imágen destacada es la mascota extraoficial de Rust.