Por qué Rust rompe esquemas (y es normal)
\n\nRust es un lenguaje-desafío. No perdona la pereza, no da tregua al «así está bien» y exige del programador un profundo entendimiento de la memoria. Por eso muchos desarrolladores, especialmente después de Python o JavaScript, experimentan un choque cultural. ¿Estás acostumbrado a que el intérprete limpie la basura por ti? Olvídalo. Rust dice: «Eres el dueño de tu memoria, pero por cada error pagarás con la compilación».
\n\nEn este artículo analizaremos 10 errores principales al aprender Rust que cometen los principiantes. No solo los enumeraremos, sino que mostraremos cómo corregirlos con código real. Si estás empezando tu camino en Rust o ya te has llevado algunos golpes, este material es para ti.
\n\nError n.º 1: Ignorar el borrow checker
\n\nLa queja más común: «¡¿Por qué el compilador se queja de todo?!». El borrow checker no es un enemigo, sino tu mejor amigo. No te deja dispararte en el pie. El problema es que los principiantes intentan evitarlo en lugar de entender su lógica.
\n\nCómo se ve un error típico
\n\nfn main() {\n let mut s = String::from("hello");\n let r1 = &s;\n let r2 = &mut s; // ¡ERROR!\n println!("{}, {}", r1, r2);\n}\n\nEl compilador mostrará: cannot borrow `s` as mutable because it is also borrowed as immutable. El principiante, en pánico, elimina mut o empieza a llenar todo de clone(). La solución correcta es reducir el ámbito de los préstamos.
Solución
\n\nfn main() {\n let mut s = String::from("hello");\n let r1 = &s;\n println!("{}", r1); // el préstamo inmutable termina aquí\n let r2 = &mut s;\n println!("{}", r2);\n}\n\nConsejo: Ve al borrow checker como a un compañero celoso: solo permite un préstamo mutable o cualquier cantidad de préstamos inmutables, pero no ambos al mismo tiempo.
\n\nError n.º 2: Miedo a los lifetimes
\n\nLos lifetimes asustan más a los principiantes. La sintaxis 'a parece magia, pero en realidad son solo anotaciones para el borrow checker que dicen: «Esta referencia vive tanto como esa».
Problema: devolver una referencia desde una función
\n\nfn longest(x: &str, y: &str) -> &str { // ERROR: falta el especificador de lifetime\n if x.len() > y.len() { x } else { y }\n}\n\nEl compilador no sabe cuál de las referencias será devuelta. La solución es indicar explícitamente que ambas referencias viven lo mismo:
\n\nfn longest<'a>(x: &'a str, y: &'a str) -> &'a str {\n if x.len() > y.len() { x } else { y }\n}\n\nTruco: En el 90% de los casos los lifetimes se pueden omitir: el compilador los infiere (elision). Si te los pide, simplemente agrega 'a y no entres en pánico.
Error n.º 3: Uso excesivo de clone()
\n\nCuando el borrow checker no deja pasar, los principiantes usan .clone(). Esto funciona, pero mata la principal ventaja de Rust: las zero-cost abstractions. El código empieza a ir lento y consumir mucha memoria.
Mal ejemplo
\n\nlet s1 = String::from("hello");\nlet s2 = s1.clone(); // ¡¿para qué?!\nprintln!("{}", s1); // funciona solo por el clone\n\n\nEs mejor usar préstamo o movimiento:
\n\nlet s1 = String::from("hello");\nlet s2 = &s1; // préstamo\nprintln!("{}", s1); // todo bien\n\n\nRegla de oro: Usa clone() solo para estructuras de datos complejas donde el préstamo sea imposible (por ejemplo, al pasar datos a otro hilo).
\n\nError n.º 4: No entender el ownership
\n\nRust es el único lenguaje donde el ownership no es una filosofía, sino una regla de compilación. Cada valor tiene exactamente un dueño. Cuando en