El lenguaje de programación más admirado por los desarrolladores, según Stack Overflow, destaca por su enfoque en el rendimiento, productividad y resistencia.

Según los resultados de la encuesta de Stack Overflow, Rust es el lenguaje de programación más admirado por los desarrolladores, con más de 80% de los encuestados. Encuesta

Stackoverflow survey

Playground

Prueba aqui tu codigo!

Código

Hola mundo

      
        fn main() {
        println!("Hello, world!");
        }
      
    

Variables y mutación

      

        fn main() {
        let mi_variable = 5; // inmutable
        let mut mi_variable_mut = 5; // mutable

        mi_variable_mut = 10;
        mi_variable = 10; // Error, no se puede modificar una variable inmutable

        }

      
    

Shadowing

      

        fn main() {
        let x = 5;
        let x = x + 1; // copia de la variable x original, pero con un valor diferente

        {
        let x = x * 2; // otra variable x, pero con un valor diferente y en un scope diferente
        println!("El valor de x en el bloque interno es: {}", x);

        }

        println!("El valor de x en el bloque principal es: {}", x);
        }

      
    

Tipos de datos

      

        fn main() {
        let x: i32 = 5;
        let y: f64 = 6.0;
        let text: &str = "Hello, world!";
        let letter: char = 'a';
        let is_valid: bool = true;

        // Tambien se puede hacer de esta forma
        let x = 5;
        let y = 6.0;
        let text = "Hello, world!";
        let letter = 'a';
        let is_valid = true;

        // Tambien se puede hacer de esta forma
        let x = 5i32;
        let y = 6.0f64;

        // Incluso se pueden hacer validaciones
        let idk: u16 = "5".parse().expect("Not a number!");
        let idk: u16 = "-5".parse().expect("Not a number!"); // Error
        }

      
    

Vectores y tuplas

      
        fn main() {
        let vector: Vec = vec![1, 2, 3, 4, 5];
          let tupla: (i32, f64, char) = (500, 6.4, 'a');

          // Acceder a los elementos de un vector
          let primer_elemento = vector[0];
          let ultimo_elemento = vector[vector.len() - 1];

          println!("El primer elemento del vector es: {}", primer_elemento);
          println!("El ultimo elemento del vector es: {}", ultimo_elemento);

          // Acceder a los elementos de una tupla
          let (x, y, z) = tupla;
          let primer_elemento = x;
          let ultimo_elemento = z;

          println!("El primer elemento de la tupla es: {}", primer_elemento);
          println!("El ultimo elemento de la tupla es: {}", ultimo_elemento);

          // Acceder a los elementos de una tupla de forma directa
          let primer_elemento = tupla.0;
          let ultimo_elemento = tupla.2;

          println!("El primer elemento de la tupla es: {}", primer_elemento);
          println!("El ultimo elemento de la tupla es: {}", ultimo_elemento);
          }
      
    

Otros tipos de datos

      
        fn main() {
        enum Review {
        Good,
        Bad,
        NotRated,
        }

        let rating = Review::Good;

        // las variables que empiezan con _ no se usan explicitamente
        let _second_rating = Review::Bad;
        let _third_rating = Review::NotRated;

        match rating {
        Review::Good => println!("This restaurant is good"),
        Review::Bad => println!("This restaurant is bad"),
        Review::NotRated => println!("This restaurant is not rated yet"),
        }


        struct Person {
        name: String,
        age: u8,
        }

        let person = Person {
        name: String::from("Samantha"),
        age: 20,
        };

        match person {
        Person { name, age } => println!("{} is {} years old", name, age),
        }
        }
      
    

Ownership y borrowing

Este ejemplo muestra como se transfiere la propiedad de una variable a otra. En este caso, la variable s1 tiene la propiedad del String y cuando se asigna a s2, la variable s1 ya no tiene la propiedad del String, por lo tanto, no se puede usar. Esto se debe a que Rust automáticamente librea la memoria de la variable s1 cuando otra variable hace referencia a la misma dirección de memoria. Esto evita que si por ejemplo salimos del scope de las variables s1 y s2 liberemos dos veces la misma dirección de memoria, lo cual conduce a un error de memoria y a posibles fallos de seguridad.
ownership explain
      
        fn main() {
        let s1 = String::from("hello");
        let s2 = s1;

        println!("{}, world!", s1); // Error, s1 ya no tiene la propiedad del String
        }
      
    
A diferencia del ejemplo anterior, ¿por qué en este caso no se produce un error? Esto se debe a que en este caso se hace una copia del valor, lo cual es algo que no está disponible para los Strings pero si para los tipos de datos: enteros, booleanos, floats, caracteres y tuplas, aunque para este ultimo, solo se puede hacer si todos los elementos de la tupla implementan el trait Copy.
      
        fn main() {
        let x = 5;
        let y = x;

        println!("x = {}, y = {}", x, y);
        }
      
    
En este caso, la función toma presetada la propiedad del String, pero no se puede modificar. Esto se debe a que las referencias también son inmutables a menos de que se especifique lo contrario.
      
        fn main() {
        let s = String::from("hello");

        change(&s);
        }

        fn change(some_string: &String) {
        some_string.push_str(", world"); // Error, no se puede modificar una referencia inmutable
        }
      
    
A diferencia del caso anterior, en este caso se puede modificar la referencia, ya que se especifica que la referencia es mutable y como además estamos tomando prestada la propiedad del String, se debe especificar que dicha variable es mutable, ya que la propiedad no se puede transfere.
      
        fn main() {
        let mut s = String::from("hello");

        change(&mut s);

        println!("The value of s is: {}", s);
        }

        fn change(some_string: &mut String) {
        some_string.push_str(", world");
        }
      
    

Concurrencia

En este ejemplo se crean dos hilos de ejecución, cada uno realiza una tarea diferente. Al final se espera a que ambos hilos terminen antes de que seguir con la ejecución del hilo principal.
      
        use std::thread;
        use std::time::Duration;

        fn main() {

        let hilo1 = thread::spawn(|| {
        for i in 1..10 {
        println!("Ciclo en el hilo 1: {}", i);
        thread::sleep(Duration::from_millis(1));
        }
        });

        let hilo2 = thread::spawn(|| {
        let mut i = 1;
        let mut msg = "";
        loop {

        if i % 2 == 0 {
        msg = "Si";
        } else {
        msg = "No";
        }

        println!("Hilo 2 - ¿i es par?: {}", msg);
        i += 1;
        thread::sleep(Duration::from_millis(1));

        if i == 10 {
        break;
        }
        }
        });


        // Permite que el hilo de ejecución principal espere a que los hilos creados terminen
        hilo1.join().unwrap();
        hilo2.join().unwrap();
        }


      
    
En este ejemplo se recrea el productor-consumidor, donde el existen varios productores que envían mensajes a un consumidor. Para esto se usa el módulo mpsc (multiple producer, single consumer). Por otra parte, se usa la palabra reservada move para que el hilo tome propiedad de las variables que se usen dentro en este caso tx para los productores y rx para el consumidor.
      
        use std::thread;
        use std::sync::mpsc;
        use std::time::Duration;

        fn main() {

        // MSC: Multiple Sender, Single Consumer
        let (tx, rx) = mpsc::channel();

        // Con la palabra reservada move, le decimos a Rust que el hilo
        // va a tomar propiedad de las variables que se usen dentro.
        let productor = thread::spawn(move || {
        let valores = vec![
        String::from("Hola"),
        String::from("este"),
        String::from("es"),
        String::from("un"),
        String::from("mensaje"),
        String::from("de"),
        String::from("prueba"),
        String::from("para"),
        String::from("la clase"),
        String::from("de"),
        String::from("Lenguajes de Programación"),
        ];

        for valor in valores {
        tx.send(valor).unwrap();
        thread::sleep(Duration::from_millis(1));
        }
        });


        let consumidor = thread::spawn(move || {
        for recibido in rx {
        println!("Recibido: {}", recibido);
        }
        });

        productor.join().unwrap();
        consumidor.join().unwrap();
        }

      
    
En este ejemplo se hace uso de Mutex, que permite que un recurso sea compartido entre hilos. También se utiliza Arc que a diferencia de Rc permite que el recurso sea compartido entre hilos de una forma segura sin tener inconvenientes de ownership.
      
        use std::sync::{Arc, Mutex, mpsc};
        use std::thread;
        use std::time::Duration;

        fn main() {
        let (tx, rx) = mpsc::channel();

        // Se crea un Mutex que contiene un entero
        // Por otra parte, Arc permite que el recurso sea compartido entre los hilos
        let contador = Arc::new(Mutex::new(0));

        // Vector de hilos
        let mut handles = vec![];

        // Creación de 10 hilos, cada uno se encarga de incrementar el contador
        for _ in 0..10 {
        let tx = tx.clone();

        // Se crea otra referencia al contador para que pueda ser usado en el hilo
        // y evitar problemas de ownership, ya que no se transfiere la propiedad del Mutex
        // sino que se crea una nueva referencia.
        let contador = Arc::clone(&contador);
        let handle = thread::spawn(move || {
        let mut num = contador.lock().unwrap();

        // Se referencia a la variable num que está dentro del Mutex, que originalmente viene de la variable contador
        *num += 2;

        tx.send(()).unwrap();
        thread::sleep(Duration::from_millis(10));
        });
        handles.push(handle);
        }

        for _ in 0..10 {
        rx.recv().unwrap();
        }

        for handle in handles {
        handle.join().unwrap();
        }

        println!("Resultado: {}", *contador.lock().unwrap());
        }

      
    

Recursos externos

Recursos oficiales o creados por la comunidad para aprender Rust.

Historial de páginas anteriores

rust-logo

En esta pagina podras encontrar recursos como tutoriales, ejemplos, documentacion y un taller.

rust-logo

Esta es una presentacion iteractiva en html de Rust, donde se explica el lenguaje de programacion se tiene notebooks de Jupyter para practicar y tambien un taller.

2019-02
rust-logo

En esta pagina podras encontrar una presentacion muy interesante asi como tambien un notedbook de Jupyter muy completo.

2021-01