Rust 101

Pequeña guía para empezar con Rust.

Tooling

Tooling en Rust.

Propiedad

Podemos fundamentalmente disponer de una variable en tres formas:

  • valor: podemos hacer lo que queramos con dicho valor
  • referencia compartida, &: podemos básicamente leer, tenemos acceso compartido con otros posibles clientes que estén usando dicha referencia
  • referencia mutable, &mut: tenemos acceso exclusivo, y podemos hacer casi de todo siempre y cuando dejemos la variable en un estado válido para los siguientes usuarios que tenga

Lifetime

Rust lifetime.

Pattern Matching

Es muy goloso descartar las ramas que no queremos procesar con _. En mi experiencia este es el camino a seguir en enum cerrados del lenguaje o librerías, o en código muy maduro y que se puede considerar ya cerrado. Pero mientras estamos en fase activa de desarrollo, provoca bugs, por lo que es preferible descartar de forma explícita para que cada vez que añadamos una variante nueva, el compilador pueda hacer su trabajo y nos aviso que no hemos tratado la nueva rama.

Keywords

No todas, sino algunas no triviales.

ref

Si tengo

struct Foo<'a> {
    foo: Option<&'a str>
}

e intento extraer el valor con

let foo = Foo::default();

if let Some(f) = foo { ... }

esto nos mueve el valor fuera de foo, lo que implica que tenemos la propiedad sobre él. Sino fuese así no podríamos moverlo. Pero puede que lo que queramos sea tener una referencia, mutable o no, al valor dentro de foo. Para eso podemos usar ref:

if let Some(ref mut f) = foo { ... }

// Esto es equivalente
if let Some(f) = &mut foo { ... }

Con esto estamos obteniendo una referencia al valor que estamos matcheando, en vez de obtener el valor en sí.

Chuleta sobre el lenguaje

  • move se usa para capturar las variables por referencia como variables por valor en una closure.
  • cuando queremos definir un tipo para un closure, y capturamos alguna variable, no podemos usar fn, sino Fn. Si no capturamos, el compilador es capaz de pasar el closure a fn. Si ha de mutar alguna variable que capture, ha de ser FnMut en vez de Fn.

Optimizaciones

Structs

  • Cuando un struct tiene un único campo, el tamaño que ocupa es exactamente el mismo que el del campo. El compilador elimina la variable y “aplana” de forma que se usa directamente el valor envuelto allí donde se gaste el struct.

Rust Null Pointer Optimization

Dispatch Dinámico

Si usamos genéricos el compilador monomorfiza, si usamos dyn y recibimos un trait en una función, se usa dispatch dinámico.

gist para toomanylinkedlist, primera implementación

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c9dcd8b6c9d191793652246ed5df298c