Rust es un lenguaje de pro­gra­ma­ción de Mozilla con el que se pueden escribir he­rra­mie­n­tas de línea de comandos, apli­ca­cio­nes web y programas de red. Además, este lenguaje también se puede usar para la pro­gra­ma­ción de bajo nivel. Entre los pro­gra­ma­do­res de Rust, el lenguaje goza de gran po­pu­la­ri­dad.

En este tutorial de Rust, te mostramos las pri­n­ci­pa­les ca­ra­c­te­rí­s­ti­cas del lenguaje. Al hacerlo, podrás observar las si­mi­li­tu­des y di­fe­re­n­cias con otros lenguajes. Te guiaremos asimismo en la in­s­ta­la­ción de Rust y apre­n­de­rás a escribir y compilar el código de Rust en tu propio sistema.

Breve in­tro­du­c­ción a Rust: aspectos clave

Rust es un lenguaje compilado, lo que garantiza un alto re­n­di­mie­n­to. Al mismo tiempo, el lenguaje pro­po­r­cio­na so­fi­s­ti­ca­das ab­s­tra­c­cio­nes que facilitan en gran medida el trabajo del pro­gra­ma­dor. La seguridad también se presenta como una de las pri­n­ci­pa­les ventajas de Rust frente a lenguajes an­te­rio­res como C y C++.

Usar Rust en un sistema propio

Dado que Rust es un software libre y de código abierto (FOSS), cua­l­quie­ra puede de­s­ca­r­gar­se la cadena de he­rra­mie­n­tas del lenguaje de pro­gra­ma­ción y uti­li­zar­la en su propio sistema. A di­fe­re­n­cia de Python o Ja­va­S­cri­pt, Rust no es un lenguaje in­te­r­pre­ta­do. En lugar de un in­té­r­pre­te, utiliza un co­m­pi­la­dor, como en C, C++ y Java. En la práctica, esto se traduce en una ejecución del código en dos pasos:

  1. Compilar el código fuente. Esto genera un archivo eje­cu­ta­ble binario.
  2. Ejecutar el archivo binario re­su­l­ta­n­te.

En el caso más simple, ambos pasos se controlan desde la interfaz de línea de comandos.

Consejo

En este otro artículo de la Digital Guide, se pro­fu­n­di­za en la di­fe­re­n­cia entre co­m­pi­la­dor e in­té­r­pre­te.

Además de los archivos binarios eje­cu­ta­bles, Rust permite también crear bi­blio­te­cas. Si el código compilado es un programa que se puede ejecutar di­re­c­ta­me­n­te, se debe definir una función main() en el código fuente. Al igual que en C/C++, esto sirve como punto de partida para ejecutar el código.

Instalar Rust en el sistema local

Para usar Rust, es necesario que primero lo instales de forma local. En macOS se puede usar el sistema de gestión de paquetes Homebrew, también co­m­pa­ti­ble con Linux. Abre la interfaz de línea de comandos (Terminal.App en Mac), copia la siguiente línea de código en la terminal y ejecútala.

brew install rust
Nota

Para instalar Rust en Windows o en otro sistema operativo donde no se pueda usar Homebrew, utiliza la he­rra­mie­n­ta oficial Rustup.

Para comprobar que Rust se ha instalado con éxito, abre una nueva ventana en la consola y ejecuta el código que aparece a co­n­ti­nua­ción:

rustc --version

Si Rust se ha instalado co­rre­c­ta­me­n­te, aparecerá la versión del co­m­pi­la­dor de Rust. En cambio, si se muestra un mensaje de error, vuelve a iniciar la in­s­ta­la­ción.

Co­m­pi­la­ción de código Rust

Para compilar el código Rust, necesitas un archivo de código fuente Rust. Abre la terminal de comandos y ejecuta los si­guie­n­tes fra­g­me­n­tos de código. Con ellos, crearemos una carpeta en el es­cri­to­rio para el tutorial de Rust y la abriremos:

cd "$HOME/Escritorio/"
mkdir rust-tutorial && cd rust-tutorial

A co­n­ti­nua­ción, se creará el archivo de código fuente de Rust con el sencillo ejemplo “Hello, World”:

cat << EOF > ./rust-tutorial.rs
fn main() {
    println!("Hello, World!");
}
EOF
Nota

Los archivos de código fuente Rust terminan en .rs.

Fi­na­l­me­n­te, se compilará el código fuente Rust y se ejecutará el archivo binario re­su­l­ta­n­te:

# Rust-compilar código fuente
rustc rust-tutorial.rs
# Ejecutar el archivo binario resultante
./rust-tutorial
Consejo

Utiliza el comando rustc rust-tutorial.rs && ./rust-tutorial para combinar los dos pasos. De esta manera podrás volver a compilar y ejecutar tu programa en la interfaz de línea de comandos pulsando la tecla de la flecha hacia arriba seguida de “Intro”.

Gestionar los paquetes de Rust con Cargo

Además del lenguaje Rust, hay una serie de paquetes externos. Los llamados Crates se pueden obtener en el Rust Package Registry. Para ello, se usa la he­rra­mie­n­ta Cargo, instalada junto con Rust. El comando cargo permite tanto la in­s­ta­la­ción de paquetes como la creación de otros nuevos. Comprueba que Cargo se ha instalado co­rre­c­ta­me­n­te:

cargo --version

Conoce los fu­n­da­me­n­tos de Rust

Para aprender a usar Rust, te re­co­me­n­da­mos que vayas probando los ejemplos de código. Para ello, puedes usar el archivo rust-tutorial.rs que hemos creado. Copia un ejemplo de código en el archivo, compílalo y ejecuta el archivo binario re­su­l­ta­n­te. Para que funcione, debes insertar el código de ejemplo dentro de la función main().

Aunque, para probar el código Rust, también puedes usar Rust Pla­y­grou­nd di­re­c­ta­me­n­te en tu navegador.

De­cla­ra­cio­nes y bloques

En Rust, las de­cla­ra­cio­nes son co­m­po­ne­n­tes de código básico. Una de­cla­ra­ción termina con un punto y coma (;) y, a di­fe­re­n­cia de una expresión, no devuelve un valor. En un mismo bloque, se pueden agrupar varias de­cla­ra­cio­nes. Como en C/C++ y Java, los bloques están de­li­mi­ta­dos por llaves ({}).

Co­me­n­ta­rios

Los co­me­n­ta­rios son una función im­po­r­ta­n­te en cualquier lenguaje de pro­gra­ma­ción. Se utilizan tanto para la do­cu­me­n­ta­ción del código, como en la pla­ni­fi­ca­ción, antes de que se escriba el código real. Para los co­me­n­ta­rios, Rust utiliza la misma sintaxis que C, C++, Java y Ja­va­S­cri­pt: todo texto incluido después de la doble barra se in­te­r­pre­ta como un co­me­n­ta­rio y el co­m­pi­la­dor lo ignora.

// Esto es un comentario
// Esto es 
// un comentario
// formado
// por varias líneas.

Variables y co­n­s­ta­n­tes

En Rust se usa la palabra clave let para declarar una variable y puede de­cla­rar­se de nuevo una variable que ya existe, so­bre­s­cri­bié­n­do­se. A di­fe­re­n­cia de muchos otros lenguajes, no es fácil cambiar el valor de una variable:

// Declarar la variable ‘edad’ y fijar el valor en ‘42’
let edad = 42;
// El valor de la variable ‘edad’ no se puede cambiar
edad = 49; // Error de compilación
// con una nueva declaración ‘let’, la variable ‘edad’ puede sobrescribirse
let edad = 49;

Para indicar que el valor de una variable se pueda cambiar con po­s­te­rio­ri­dad, Rust propone la palabra clave mut. El valor de una variable declarada con mut sí puede cambiarse:

let mut peso = 78;
peso = 75;

Con la palabra clave const se define una constante. El valor de una constante en Rust debe ser conocido en el momento de la co­m­pi­la­ción. Asimismo, el tipo debe es­pe­ci­fi­car­se de forma explícita:

const VERSION: &str = "1.46.0";

El valor de una constante no se puede cambiar. Una constante tampoco puede de­cla­rar­se como mut, ni puede so­bre­s­cri­bi­r­se:

// Definir constantes
const MAX_NUM: u8 = 255;
MAX_NUM = 0; // Error al compilar, pues el valor de la constante no se puede cambiar 
const MAX_NUM = 0; // Error al compilar, pues el valor de la constante no se puede volver a declarar

Modelo de propiedad

Una de las ca­ra­c­te­rí­s­ti­cas más im­po­r­ta­n­tes de Rust es el modelo de propiedad (en inglés, ownership). La propiedad está es­tre­cha­me­n­te re­la­cio­na­da con el valor de las variables, su vida útil y la gestión del al­ma­ce­na­mie­n­to de los objetos en la memoria heap. Cuando una variable sale del rango válido (Scope), su valor se destruye y la memoria se libera. Por lo tanto, Rust puede pre­s­ci­n­dir del re­co­le­c­tor de basura, lo que favorece un alto re­n­di­mie­n­to.

Cada valor de Rust pertenece a una variable, el pro­pie­ta­rio. Solo puede haber un pro­pie­ta­rio para cada valor. Si el pro­pie­ta­rio cede el valor a otra variable, entonces deja de ser pro­pie­ta­rio:

let name = String::from("Ana Ejemplo");
let _name = name;
println!("{}, world!", name); // Error de compilación, dado que el valor ‘name’ dirige a ‘name’

Hay que tener especial cuidado con la de­fi­ni­ción de las funciones. Si se pasa una variable a una función, el pro­pie­ta­rio del valor cambia. La variable no puede volver a uti­li­zar­se después de la llamada a la función. Aquí, Rust recurre a un truco. En lugar de trasladar el valor a la función, se declara una re­fe­re­n­cia con el signo et (&). Esto permite “prestar” el valor de una variable, como se aprecia en el ejemplo:

let name = String::from("Ana Ejemplo");
// si el tipo del parámetro ‘name’ se define como ‘String’ en lugar de ‘&String’
// la variable ‘name’ ya no puede utilizarse después de la llamada de la función
fn hello(name: &String) {
    println!("Hello, {}", name);
}
// el argumento de la función también debe contener ‘&’
// como referencia
hello(&name);
// esta línea, al no usar referencia, conduce a un error de compilación
println!("hello, {}", name);

Es­tru­c­tu­ras de control

Una propiedad básica de la pro­gra­ma­ción es hacer que la ejecución del programa no sea lineal. Un programa puede ra­mi­fi­car­se y sus co­m­po­ne­n­tes pueden eje­cu­tar­se más de una vez. Es esta ve­r­sa­ti­li­dad lo que hace que un programa sea realmente útil.
Rust cuenta con las es­tru­c­tu­ras de control di­s­po­ni­bles en la mayoría de los lenguajes de pro­gra­ma­ción. Estos incluyen las co­n­s­tru­c­cio­nes en bucle for y while, así como la ra­mi­fi­ca­ción a través de if y else. Sin embargo, Rust cuenta también con algunas ca­ra­c­te­rí­s­ti­cas es­pe­cia­les. La palabra clave match permite la asi­g­na­ción de patrones, mientras que la de­cla­ra­ción loop crea un bucle infinito. Para que esto último sea práctico, se recurre a la de­cla­ra­ción break.

Bucles

La ejecución repetida de un bloque de código mediante bucles se conoce también como iteración. A menudo, la iteración se produce en los elementos de un co­n­te­ne­dor. Al igual que Python, Rust utiliza también el concepto de iterador. Un iterador abstrae el acceso sucesivo a los elementos de un co­n­te­ne­dor. Por ejemplo:

// Lista con nombres
let nombres = ["Jim", "Jack", "John"];
// bucle ‘for’ con iterador en la lista
for name in namen.iter() {
    println!("Hello, {}", name);
}

¿Y si quieres escribir un bucle for como en C/C++ o Java? Si quieres es­pe­ci­fi­car un número de inicio y un número final y recorrer todos los valores in­te­r­me­dios, Rust cuenta, igual que Python, con el objeto rango. Esto a su vez crea un iterador en el que opera la palabra clave for:

// Introducir las cifras del ‘1’ al ‘10’
// bucle ‘for’ con iterador ‘range’
// Importante: el rango no contiene la cifra final
for cifra in 1..11 {
    println!("Cifra: {}", cifra);
}
// alternativa que incluye la notación del rango
for cifra in 1..=10 {
    println!("Cifra: {}", cifra);
}

El bucle while funciona en Rust como en la mayoría de los lenguajes de pro­gra­ma­ción. Se establece una condición y se ejecuta el cuerpo del bucle siempre y cuando la condición sea cierta:

// emitir las cifras del ‘1’ al ‘10’ a través del bucle ‘while’
let mut cifra = 1;
while (cifra <= 10) {
    println!(Cifra: {}, cifra);
    cifra += 1;
}

En todos los lenguajes de pro­gra­ma­ción, es posible es­ta­ble­cer un bucle infinito con while. Aunque no­r­ma­l­me­n­te esto se considera un error, existen casos en los que puede ser necesario. En esos casos, Rust aconseja usar loop:

// Bucle infinito con ‘while’
while true {
    // …
}
// Bucle infinito con ‘loop’
loop {
    // …
}

En ambos casos, se puede recurrir a la palabra clave break para romper el bucle.

En ambos casos, se puede recurrir a la palabra clave break para romper el bucle.

Ra­mi­fi­ca­cio­nes

Las ra­mi­fi­ca­cio­nes con if y else funcionan en Rust igual que en otros lenguajes de pro­gra­ma­ción similares:

const limit: u8 = 42;
let cifra = 43;
if cifra < límite {
    println!("Por debajo del límite.");
}
else if cifra == limit {
    println!("En el límite…");
}
else {
    println!("Sobre el límite");
}

Más in­te­re­sa­n­te es la palabra clave match, con una función parecida a la de­cla­ra­ción switch en otros lenguajes de pro­gra­ma­ción. Como ejemplo, echa un vistazo a la función símbolode_carta() en la sección “Tipos de datos co­m­pue­s­tos”.

Funciones, pro­ce­di­mie­n­tos y métodos

En la mayoría de los lenguajes de pro­gra­ma­ción, las funciones son el elemento básico de la pro­gra­ma­ción modular. En Rust, las funciones se definen con la palabra clave fn. No se hace una di­s­ti­n­ción estricta entre los conceptos función y pro­ce­di­mie­n­to, que se definen de forma casi idéntica.

En sentido estricto, una función devuelve un valor. Aunque, como muchos otros lenguajes de pro­gra­ma­ción, Rust también cuenta con pro­ce­di­mie­n­tos, esto es, funciones que no devuelven ningún valor. La única re­s­tri­c­ción fija es que el tipo de retorno de una función debe es­pe­ci­fi­car­se de forma explícita. Si no se es­pe­ci­fi­ca ningún tipo de retorno, la función no puede devolver un valor. En este caso, se define como pro­ce­di­mie­n­to.

fn procedimiento() {
    println!("Este procedimiento no devuelve ningún valor.");
}
// negar una cifra
// Tipo de retorno tras el operador ‘->’
fn negado(cifra completa: i8) -> i8 {
    return cifra completa * -1;
}

Además de funciones y pro­ce­di­mie­n­tos, Rust también trabaja con métodos conocidos de la pro­gra­ma­ción orientada a objetos. Un método es una función que está ligada a una es­tru­c­tu­ra de datos. Como en Python, los métodos en Rust se definen con el primer parámetro self. La llamada a un método se realiza según el esquema habitual object.method(). A co­n­ti­nua­ción, se muestra un ejemplo del method surface(), ligado a una es­tru­c­tu­ra de datos struct:

// definición ‘struct’ 
struct rectángulo {
    ancho: u32,
    alto: u32,
}
// Implementación ‘struct’
impl rectángulo {
    fn superficie(&self) -> u32 {
        return self.ancho * self.alto;
    }
}
let rectángulo = Rectángulo {
    ancho: 30,
    alto: 50,
};
println!("El área del rectángulo es {}.", superficie.rectángulo());

Tipos de datos y es­tru­c­tu­ras de datos

Rust es un lenguaje que usa un tipado estático. A di­fe­re­n­cia de los lenguajes dinámicos como Python, Ruby, PHP o Ja­va­S­cri­pt, en Rust tiene conocerse el tipo de cada variable cuando tiene lugar la co­m­pi­la­ción.

Tipos de datos pri­mi­ti­vos

Como la mayoría de los lenguajes de pro­gra­ma­ción su­pe­rio­res, Rust posee algunos tipos de datos ele­me­n­ta­les (o “pri­mi­ti­vos”). Las in­s­ta­n­cias de tipos de datos ele­me­n­ta­les se asignan a la pila, que cuenta con un alto re­n­di­mie­n­to. Además, los valores de los tipos de datos ele­me­n­ta­les pueden definirse uti­li­za­n­do una sintaxis “literal”, es decir, basta con escribir los valores.

Tipo de dato Ex­pli­ca­ción Anotación de tipo
Integer Entero i8, u8, etc.
Floating point Valores de puntos flotantes f64, f32
Boolean Valor verdadero bool
Character Carácter char
String Cadena de ca­ra­c­te­res unicode str

Aunque Rust es un lenguaje es­tá­ti­ca­me­n­te tipado, el tipo de un valor no siempre tiene que de­cla­rar­se de forma explícita. En muchos casos, el co­m­pi­la­dor puede deducir el tipo a partir del contexto (in­fe­re­n­cia de tipos). Si no es el caso, el tipo se es­pe­ci­fi­ca ex­plí­ci­ta­me­n­te mediante una anotación de tipo, que en algunos casos es incluso obli­ga­to­ria:

  • El tipo de retorno de una función siempre debe es­pe­ci­fi­car­se ex­plí­ci­ta­me­n­te.
  • El tipo de una constante también debe es­pe­ci­fi­car­se siempre ex­plí­ci­ta­me­n­te.
  • Los strings literales deben tratarse de forma especial, para que se conozca su tamaño en la co­m­pi­la­ción.

Aquí se incluyen algunos ejemplos en los que se crean in­s­ta­n­cias de tipos de datos ele­me­n­ta­les con sintaxis literal.

// el compilador reconoce aquí de forma automática el tipo de variable
let cents = 42;
// anotación de tipo: cifra positiva (‚u8‘ = "unsigned, 8 bits")
let edad: u8 = -15; // error de compilación, ya que se ha proporcionado una cifra negativa
// Valores de puntos flotantes
let ángulo = 38,5;
// equivalente a
let ángulo: f64 = 38,5;
// Valor verdadero
let usuario_registrado = true;
// equivalente a
let usuario_registrado: bool = true;
// el carácter requiere comillas simples
let carácter = 'a';
// cadena de caracteres estática requiere comillas 
let nombre = "Ana";
// con tipo explícito
let nombre: &'static str = "Ana";
// alternativa como string dinámico con string::from()
let nombre: string = string::from("Ana");

Tipos de datos co­m­pue­s­tos

Los tipos de datos ele­me­n­ta­les re­pro­du­cen valores in­di­vi­dua­les, mientras que los tipos de datos co­m­pue­s­tos agrupan varios valores. Rust pro­po­r­cio­na a los pro­gra­ma­do­res una gran variedad de tipos de datos co­m­pue­s­tos.

Tanto las in­s­ta­n­cias de los tipos de datos co­m­pue­s­tos, como las in­s­ta­n­cias de los tipos de datos ele­me­n­ta­les, se asignan a la pila. Para ello, las in­s­ta­n­cias deben tener un tamaño de­te­r­mi­na­do. Esto también significa que después de la in­s­ta­n­cia­ción no se pueden cambiar de forma ar­bi­tra­ria. Entre los pri­n­ci­pa­les datos co­m­pue­s­tos de Rust se en­cue­n­tran:

Tipo de datos Ex­pli­ca­ción Tipo del elemento Sintaxis literal
Array Lista de varios valores El mismo tipo [a1, a2, a3]
Tuple Di­s­po­si­ción de varios valores Cualquier tipo (t1, t2)
Struct Agru­pa­ción de varios valores nombrados Cualquier tipo –
Enum Enu­me­ra­ción Cualquier tipo –

Veamos primero una es­tru­c­tu­ra de datos struct. Definimos una persona con tres campos de nombre:

struct Persona = {
    nombre: String,
    apellido: String,
    edad: u8,
}

Para re­pre­se­n­tar a una persona concreta, se instancia struct:

let jugador = Persona {
    nombre: String::from("Ana"),
    apellido: String::from("Ejemplo"),
    edad: 42,
};
// acceder al campo de una instancia struct
println!("Edad del jugador es: {}", jugador.edad);

enum (enu­me­ra­ción) re­pre­se­n­ta las posibles variantes de una propiedad. Aquí se muestra un ejemplo con los cuatro palos presentes en una baraja de cartas:

enum palosdelabaraja {
    Trébol,
    Pica,
    Corazón,
    Diamante,
}
// los palos de una baraja de cartas
let palo = palodebaraja::trébol;

Rust utiliza la palabra clave match para buscar patrones, lo que se conoce como pattern matching. Su fu­n­cio­na­li­dad puede co­m­pa­rar­se con la de­cla­ra­ción switch de otros lenguajes. Aquí hay un ejemplo:

// determinar el símbolo que pertenece a cada palo
fn símbolode_carta(palo: PaloDeLaBaraja) -> &'static str {
    match palo {
        Palo::Trébol => "♣︎",
        Palo::Pica => "♠︎",
        Palo::Corazón => "♥︎",
        Palo::Diamante => "♦︎",
    }
}
println!("Symbol: {}", símbolo_carta(Palo::Trébol)); // mostrar el símbolo ♣︎

Una tupla es la di­s­po­si­ción de varios valores, que pueden ser de di­fe­re­n­tes tipos. Los valores in­di­vi­dua­les de la tupla pueden asignarse a varias variables mediante des­es­tru­c­tu­ra­ción. Si uno de los valores no es necesario, se utiliza el guion bajo (_) como marcador de posición, como es habitual en Haskell ,Python y Ja­va­S­cri­pt. He aquí un ejemplo

// Definir la carta como tupla
let carta: (PaloDeLaCarta, u8) = (PaloDeLaCarta::Corazón, 7);
// Asignar los valores de una tupla a varias variables
let (palo, valor) = carta;
// en caso de necesitar el valor
let (_, valor) = carta;

Dado que los valores de la tupla están ordenados, también es posible acceder a ellos mediante un índice numérico. Para la in­de­xa­ción no se utilizan corchetes, sino que se recurre a la sintaxis de puntos. En la mayoría de los casos, la des­es­tru­c­tu­ra­ción debería resultar en un código más legible:

let Nombre completo = ("Ana", "Ejemplo");
let nombre = name.0;
let apellido = name.1;

Aprender co­n­s­tru­c­cio­nes de pro­gra­ma­ción su­pe­rio­res en Rust

Es­tru­c­tu­ras de datos dinámicos

Las in­s­ta­n­cias de los tipos de datos co­m­pue­s­tos pre­se­n­ta­dos se asignan a la pila. Sin embargo, la bi­blio­te­ca estándar de Rust también contiene una serie de es­tru­c­tu­ras de datos dinámicos de uso común. Las in­s­ta­n­cias de estas es­tru­c­tu­ras de datos se asignan a la memoria heap, lo que implica que el tamaño de las in­s­ta­n­cias puede cambiarse a po­s­te­rio­ri. A co­n­ti­nua­ción, pre­se­n­ta­mos bre­ve­me­n­te las es­tru­c­tu­ras de datos dinámicos que se usan con mayor fre­cue­n­cia:

Tipo de datos Ex­pli­ca­ción
Vector Lista dinámica de varios valores del mismo tipo
String Secuencia dinámica de ca­ra­c­te­res Unicode
HashMap Asi­g­na­ción dinámica de los pares clave-valor

A co­n­ti­nua­ción, te mostramos un ejemplo de vector de cre­ci­mie­n­to dinámico:

// Declarar el vector con mut como modificable 
let mut nombre = Vec::new();
// Añadir valores al vector
nombres.push("Jim");
nombres.push("Jack");
nombres.push("John");

Pro­gra­ma­ción orientada a objetos (OOP) en Rust

A di­fe­re­n­cia de lenguajes como C++ y Java, Rust no conoce el concepto de clases. Sin embargo, es posible programar según la me­to­do­lo­gía OOP, uti­li­za­n­do como base los tipos de datos ya pre­se­n­ta­dos. El tipo struct puede usarse para definir la es­tru­c­tu­ra de los objetos.

Además, Rust también cuenta con los traits. Un trait engloba un conjunto de métodos que cualquier tipo puede im­ple­me­n­tar. Comprende, además, de­cla­ra­cio­nes de método, aunque también puede contener im­ple­me­n­ta­cio­nes. En lo que al concepto se refiere, un trait se encuentra entre una interfaz de Java y una clase base abstracta.

Un trait que ya existe puede ser im­ple­me­n­ta­do por di­fe­re­n­tes tipos. A su vez, un tipo puede im­ple­me­n­tar varios traits. Rust permite así la co­m­po­si­ción de la fu­n­cio­na­li­dad para di­fe­re­n­tes tipos sin necesidad de un an­te­ce­de­n­te común.

Pro­gra­ma­ción meta

Como muchos otros lenguajes de pro­gra­ma­ción, Rust permite escribir código para la me­ta­pro­gra­ma­ción. Se trata de un código que genera más código. En Rust se en­cue­n­tran, por un lado, las macros, que terminan con un signo de ex­cla­ma­ción (!) y que puedes conocer de C/C++. La macro println!, para mostrar texto en la línea de comandos, ya se ha me­n­cio­na­do varias veces en este artículo.

Por otro lado, Rust también recurre a los llamados genéricos, que permiten escribir código que se puede abstraer en varios tipos. Los genéricos son co­m­pa­ra­bles con las pla­n­ti­llas en C++ o a los también llamados genéricos en Java. Un genérico que se usa a menudo en Rust es Option<T>, que abstrae la dualidad Ninguno/Algunos(T) para cualquier tipo de T.

En resumen

Rust tiene el potencial de re­em­pla­zar a los populares C y C++ como lenguaje de pro­gra­ma­ción de sistemas.

Ir al menú principal