From 7747177df73e01707531bde5eff257a0aead1981 Mon Sep 17 00:00:00 2001 From: Sergio Ribera <56278796+SergioRibera@users.noreply.github.com> Date: Fri, 23 Aug 2024 23:36:22 -0400 Subject: [PATCH 1/7] fix: change position --- content/3.error-handling/1.option.md | 139 ++++++++++++++------------- 1 file changed, 71 insertions(+), 68 deletions(-) diff --git a/content/3.error-handling/1.option.md b/content/3.error-handling/1.option.md index a8dbc46..9d411e0 100644 --- a/content/3.error-handling/1.option.md +++ b/content/3.error-handling/1.option.md @@ -6,27 +6,30 @@ data: type: 'custom' topicLevel: 'start' position: - x: -700 - y: 320 + x: 255 + y: 520 width: 320 externalLinks: - name: 'Libro Oficial' english: false - link: 'https://book.rustlang-es.org/ch03-01-variables-and-mutability#shadowing' + link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum' - name: 'Comprehensive Rust' english: false - link: 'https://google.github.io/comprehensive-rust/es/control-flow-basics/blocks-and-scopes.html?highlight=shado#%C3%81mbitos-y--shadowing' + link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html' + - name: 'Documentacion Oficial' + english: true + link: 'https://doc.rust-lang.org/std/option' + - name: '¿Cómo almacena Rust los enum en memoria?' + english: false + link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria' --- -# Option en Rust: Manejo Seguro de Valores Opcionales +## Entendiendo el Tipo `Option` en Rust: Seguridad y Ausencia de Valores Nulos + +En Rust, el tipo `Option` es una herramienta fundamental que permite manejar de forma segura la ausencia de un valor sin recurrir al temido null. En lugar de utilizar valores nulos que pueden llevar a errores inesperados, Rust introduce `Option`, que garantiza que el manejo de valores opcionales sea explícito y seguro. -## Introducción -En Rust, el tipo Option es una característica clave para el manejo seguro de valores que pueden o no estar presentes. Option evita errores -comunes como los de referencias nulas, proporcionando una alternativa robusta y segura para representar valores opcionales. En este -artículo, exploraremos el uso y las ventajas del tipo Option en Rust. +### ¿Qué es un `Option`? -### Concepto de Option en Rust -Option es una enumeración que puede contener un valor (Some(T)) o no (None). Este enfoque asegura que el programador maneje explícitamente -los casos donde un valor puede estar ausente, mejorando así la seguridad y la robustez del código. +`Option` es un enum predefinido en Rust que puede tomar dos valores: ```rust enum Option { @@ -34,84 +37,84 @@ enum Option { None, } ``` -### Definición y Uso Básico -Option se define en la biblioteca estándar de Rust y se usa comúnmente en situaciones donde un valor puede o no estar presente. -Aquí tienes un ejemplo básico: +- `Some(T)` indica que hay un valor presente. +- `None` representa la ausencia de un valor. -```rust -fn find_index(arr: &[i32], target: i32) -> Option { - for (index, &item) in arr.iter().enumerate() { - if item == target { - return Some(index); - } - } - None -} -``` -En este ejemplo, la función find_index devuelve Some(index) si encuentra el target en el arreglo, y None si no lo encuentra. +### Funciones Comunes para Trabajar con `Option` -## Ejemplos de Uso de Option +Rust ofrece múltiples funciones para manipular opciones de forma segura: -### Acceso Seguro a Elementos -Al acceder a elementos en estructuras de datos, Option asegura que manejemos adecuadamente los casos donde los elementos pueden no -existir. +- **is_some() e is_none():** Verifican si un `Option` contiene un valor o no. + + ```rust + let maybe_value: Option = Some(5); + assert!(maybe_value.is_some()); -```rust -let arr = [1, 2, 3, 4, 5]; -let element = arr.get(2); // Devuelve Option<&i32> + let no_value: Option = None; + assert!(no_value.is_none()); + ``` -match element { - Some(value) => println!("Elemento en el índice 2: {}", value), - None => println!("No hay elemento en el índice 2"), -} -``` +- **unwrap() y expect():** Extraen el valor del `Option`, pero si es `None`, `unwrap()` causará un pánico. `expect()` permite proporcionar un mensaje de error personalizado. -### Operaciones que Pueden Fallar -Option se usa en funciones donde una operación puede no tener un resultado válido. + ```rust + let value = maybe_value.unwrap(); // Devuelve 5 o causa un pánico si es None. + ``` -```rust -fn divide(a: f64, b: f64) -> Option { - if b == 0.0 { - None - } else { - Some(a / b) - } -} -``` +- **map():** Permite aplicar una función al valor dentro de un `Option`, devolviendo un nuevo `Option`. -### Uso de Métodos de Option -Rust proporciona métodos útiles para trabajar con Option, como map, and_then, unwrap_or, entre otros. + ```rust + let maybe_value: Option = Some(5); + let maybe_double = maybe_value.map(|x| x * 2); + assert_eq!(maybe_double, Some(10)); + ``` -```rust -let some_number = Some(10); +- **and(), or() y xor():** Estas funciones permiten combinar opciones de manera segura. -let new_number = some_number.map(|x| x + 1); + ```rust + let a: Option = Some(2); + let b: Option = Some(3); + let c: Option = None; -assert_eq!(new_number, Some(11)); -``` + assert_eq!(a.and(b), Some(3)); // Devuelve Some(3) + assert_eq!(a.or(c), Some(2)); // Devuelve Some(2) + assert_eq!(c.or(a), Some(2)); // Devuelve Some(2) + ``` -## Beneficios de Option -1.**Seguridad en Tiempo de Compilación:**Option hace que los desarrolladores consideren y manejen explícitamente los casos donde un valor -puede no estar presente, lo que resulta en un código más robusto. -2.**Manejo Explícito de Casos de Ausencia:**Option hace que los desarrolladores consideren y manejen explícitamente los casos donde un -valor puede no estar presente, lo que resulta en un código más robusto. -3.**Compatibilidad con Funciones de Alto Nivel:**Option se integra bien con funciones de alto nivel y características funcionales como -map, and_then, unwrap_or, etc., permitiendo transformaciones y manejos eficientes de valores opcionales. +### Pattern Matching con `Option` -## Conclusión -El tipo Option en Rust es una herramienta poderosa para el manejo seguro de valores opcionales. Al eliminar la posibilidad de referencias nulas -y forzar a los desarrolladores a manejar explícitamente los casos de ausencia de valores, Option contribuye significativamente a la -robustez y seguridad del código en Rust. Su uso extensivo en situaciones donde los valores pueden estar presentes o no, junto con sus -métodos y transformaciones funcionales, hacen de Option una parte esencial del ecosistema de Rust. +El pattern matching es una forma común de interactuar con `Option`. Permite realizar acciones diferentes según el estado de la opción (si es `Some` o `None`): +```rust +let maybe_number = Some(10); +match maybe_number { + Some(value) => println!("El valor es: {}", value), + None => println!("No hay valor"), +} +``` + +### Interactuar con Múltiples `Option` +Cuando trabajas con múltiples `Option`, puedes combinarlas utilizando combinadores como `and_then()` o emplear pattern matching para manejar múltiples opciones simultáneamente: +```rust +let x: Option = Some(2); +let y: Option = Some(3); +let result = x.and_then(|x_val| { + y.map(|y_val| x_val + y_val) +}); +assert_eq!(result, Some(5)); +``` +### Funcionamiento en Memoria +Rust optimiza la representación en memoria de `Option`. Si `T` es un tipo que puede tener un valor que represente la ausencia de datos (por ejemplo, punteros o números enteros), Rust puede usar una optimización para no consumir espacio adicional para `Option`. De este modo, `Option` es tan eficiente en memoria como el propio tipo base. +### Conclusión +`Option` es un poderoso reemplazo para los valores nulos, brindando seguridad y claridad al código. Al ser un enum, proporciona flexibilidad y un control robusto sobre situaciones donde un valor puede o no estar presente. Al utilizar funciones como `map()`, `unwrap()`, y combinadores, puedes manejar opciones de forma elegante y segura, mientras el pattern matching te permite gestionar fácilmente las variantes de `Option` según tus necesidades. +Rust garantiza que al trabajar con `Option`, la ausencia de un valor siempre se trate de manera explícita, evitando así una de las fuentes más comunes de errores en otros lenguajes de programación. From dfb8fcfee77babeb40630efb0147a39409d657f9 Mon Sep 17 00:00:00 2001 From: Sergio Ribera <56278796+SergioRibera@users.noreply.github.com> Date: Fri, 23 Aug 2024 03:00:02 -0400 Subject: [PATCH 2/7] refactor: rename index to yml --- content/3.error-handling/{index.md => index.yml} | 1 - 1 file changed, 1 deletion(-) rename content/3.error-handling/{index.md => index.yml} (96%) diff --git a/content/3.error-handling/index.md b/content/3.error-handling/index.yml similarity index 96% rename from content/3.error-handling/index.md rename to content/3.error-handling/index.yml index 178a0fb..4c9a8dc 100644 --- a/content/3.error-handling/index.md +++ b/content/3.error-handling/index.yml @@ -13,4 +13,3 @@ data: targetPosition: cargo: 'bottom' --- -# Titulo From d834be0855c1b3809744832cae9640eddbe849df Mon Sep 17 00:00:00 2001 From: Sergio Ribera <56278796+SergioRibera@users.noreply.github.com> Date: Sat, 31 Aug 2024 00:31:25 -0400 Subject: [PATCH 3/7] fix: rename text of link buttons --- content/3.error-handling/1.option.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/3.error-handling/1.option.md b/content/3.error-handling/1.option.md index 9d411e0..3be3df8 100644 --- a/content/3.error-handling/1.option.md +++ b/content/3.error-handling/1.option.md @@ -13,10 +13,10 @@ data: - name: 'Libro Oficial' english: false link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum' - - name: 'Comprehensive Rust' + - name: 'Documentacion Oficial' english: false link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html' - - name: 'Documentacion Oficial' + - name: 'Comprehensive Rust' english: true link: 'https://doc.rust-lang.org/std/option' - name: '¿Cómo almacena Rust los enum en memoria?' From 66bdffb3c0657b2f7fa22441a11094904ca8a972 Mon Sep 17 00:00:00 2001 From: Sergio Ribera <56278796+SergioRibera@users.noreply.github.com> Date: Sat, 31 Aug 2024 01:13:57 -0400 Subject: [PATCH 4/7] feat: add result entry --- content/3.error-handling/2.result.md | 151 +++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 content/3.error-handling/2.result.md diff --git a/content/3.error-handling/2.result.md b/content/3.error-handling/2.result.md new file mode 100644 index 0000000..6c98b13 --- /dev/null +++ b/content/3.error-handling/2.result.md @@ -0,0 +1,151 @@ +--- +title: 'Results' +description: 'Result es una enumeración en Rust que se utiliza para representar valores que pueden fallar' +draft: true +data: + type: 'custom' + topicLevel: 'start' + position: + x: 255 + y: 520 + width: 320 + externalLinks: + - name: 'Libro Oficial' + english: false + link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum' + - name: 'Documentacion Oficial' + english: false + link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html' + - name: 'Comprehensive Rust' + english: true + link: 'https://doc.rust-lang.org/std/option' + - name: '¿Cómo almacena Rust los enum en memoria?' + english: false + link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria' +--- +## El Tipo `Result` en Rust: Manejo Seguro de Errores + +Uno de los principios fundamentales de Rust es la seguridad, tanto en la concurrencia como en el manejo de errores. En lugar de depender de excepciones como en otros lenguajes, Rust utiliza el tipo `Result` para manejar errores de forma explícita y segura. Este enfoque reduce la posibilidad de errores inesperados y garantiza que los desarrolladores gestionen los errores correctamente. + +### ¿Qué es un `Result`? + +`Result` es un enum predefinido en Rust que se utiliza para representar el resultado de operaciones que pueden fallar. Su definición es la siguiente: + +```rust +enum Result { + Ok(T), + Err(E), +} +``` + +- `Ok(T)`: Indica que la operación fue exitosa y contiene un valor del tipo `T`. +- `Err(E)`: Indica que la operación falló y contiene un valor del tipo `E`, que normalmente describe el error. + +### Funciones Comunes para Trabajar con `Result` + +Rust proporciona múltiples métodos para manipular y controlar el flujo de errores de manera explícita. Algunas de las funciones más comunes son: + +- **is_ok() e is_err():** Estas funciones permiten verificar si un `Result` contiene un valor exitoso o un error. + + ```rust + let result: Result = Ok(10); + assert!(result.is_ok()); + + let error: Result = Err("Error!"); + assert!(error.is_err()); + ``` + +- **unwrap() y expect():** Extraen el valor de un `Result`. Si es un `Ok`, devuelven el valor; si es un `Err`, `unwrap()` causa un pánico. `expect()` es similar, pero permite proporcionar un mensaje de error personalizado. + + ```rust + let result: Result = Ok(5); + let value = result.unwrap(); // Devuelve 5 + + let error: Result = Err("Error!"); + let value = error.expect("Algo salió mal"); // Causa un pánico con el mensaje proporcionado + ``` + +- **map() y map_err():** `map()` permite aplicar una función al valor contenido en `Ok`, mientras que `map_err()` aplica una función al valor contenido en `Err`. + + ```rust + let result: Result = Ok(2); + let doubled = result.map(|x| x * 2); + assert_eq!(doubled, Ok(4)); + + let error: Result = Err("Error!"); + let new_error = error.map_err(|e| format!("Ocurrió: {}", e)); + assert_eq!(new_error, Err("Ocurrió: Error!".to_string())); + ``` + +- **and_then():** Permite encadenar operaciones que también devuelven `Result`, facilitando la propagación de errores. + + ```rust + let result: Result = Ok(2); + let chained_result = result.and_then(|x| Ok(x * 3)); + assert_eq!(chained_result, Ok(6)); + ``` + +### Pattern Matching con `Result` + +El pattern matching es una técnica poderosa en Rust que se usa a menudo para manejar `Result`. Con `match`, puedes manejar tanto los casos exitosos como los errores de manera explícita: + +```rust +let result: Result = Ok(10); + +match result { + Ok(value) => println!("El valor es: {}", value), + Err(error) => println!("Error: {}", error), +} +``` + +### Interactuar con Múltiples `Result` + +Cuando trabajas con múltiples resultados que pueden fallar, puedes combinarlos utilizando combinadores o emplear pattern matching para manejar las diversas posibilidades. Aquí un ejemplo sencillo usando `and_then()` para encadenar operaciones que pueden fallar: + +```rust +let x: Result = Ok(2); +let y: Result = Ok(3); + +let result = x.and_then(|x_val| { + y.map(|y_val| x_val + y_val) +}); + +assert_eq!(result, Ok(5)); +``` + +### Funcionamiento en Memoria + +El tipo `Result`, al igual que `Option`, es representado de manera eficiente en memoria. Dado que `Result` es un enum, el compilador ajusta su representación en memoria según el tipo de datos que contiene. Al trabajar con un `Result`, Rust optimiza el almacenamiento para que no haya un sobrecoste significativo en comparación con otras representaciones de errores. + +Cuando se utiliza `Result`, el tamaño en memoria depende tanto del valor contenido en `Ok` como del valor contenido en `Err`. Si bien ambos pueden ser diferentes, el compilador se encarga de ajustar su representación para minimizar el espacio de almacenamiento. + +### Comparación con `Option` + +A diferencia de `Option`, que representa la presencia o ausencia de un valor, `Result` se utiliza principalmente para manejar operaciones que pueden fallar. Aunque ambos son enums, `Result` es más adecuado para representar errores porque incluye el valor `Err` que proporciona información adicional sobre qué salió mal. + +### Ejemplo Completo de Uso de `Result` + +Aquí un ejemplo práctico de cómo podrías utilizar `Result` para manejar una operación de apertura de archivos, que puede fallar si el archivo no existe: + +```rust +use std::fs::File; +use std::io::{self, Read}; + +fn leer_archivo(path: &str) -> Result { + let mut archivo = File::open(path)?; + let mut contenido = String::new(); + archivo.read_to_string(&mut contenido)?; + Ok(contenido) +} + +fn main() { + match leer_archivo("archivo.txt") { + Ok(contenido) => println!("Contenido: {}", contenido), + Err(error) => println!("No se pudo leer el archivo: {}", error), + } +} +``` + +### Conclusión + +El tipo `Result` es una herramienta poderosa para el manejo seguro de errores en Rust. Al ser un enum con las variantes `Ok` y `Err`, te obliga a manejar explícitamente los posibles fallos en las operaciones. Gracias a métodos como `map()`, `and_then()` y `unwrap()`, junto con el pattern matching, el manejo de errores en Rust es mucho más robusto y menos propenso a errores que en otros lenguajes. Además, al ser altamente eficiente en memoria, `Result` es una elección óptima para el manejo de errores en aplicaciones de alta performance. From ae96fbee84a7b8246d0255cd3eafcd5dc0e2fd51 Mon Sep 17 00:00:00 2001 From: Sergio Ribera <56278796+SergioRibera@users.noreply.github.com> Date: Sat, 7 Sep 2024 23:53:07 -0400 Subject: [PATCH 5/7] feat: add error operator --- content/3.error-handling/3.operator.md | 137 +++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 content/3.error-handling/3.operator.md diff --git a/content/3.error-handling/3.operator.md b/content/3.error-handling/3.operator.md new file mode 100644 index 0000000..5ed240e --- /dev/null +++ b/content/3.error-handling/3.operator.md @@ -0,0 +1,137 @@ +--- +title: 'Operador de Propagación (`?`)' +description: 'Mejorando el manejo de errores con el Operador de Propagación (`?`)' +draft: true +data: + type: 'custom' + topicLevel: 'start' + position: + x: 255 + y: 520 + width: 320 + externalLinks: + - name: 'Libro Oficial' + english: false + link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum' + - name: 'Documentacion Oficial' + english: false + link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html' + - name: 'Comprehensive Rust' + english: true + link: 'https://doc.rust-lang.org/std/option' + - name: '¿Cómo almacena Rust los enum en memoria?' + english: false + link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria' +--- +## Uso del Operador de Propagación (`?`) en Rust con `Option` y `Result` + +Rust ofrece un enfoque único y eficiente para manejar errores y valores opcionales mediante los tipos `Option` y `Result`. Para facilitar la propagación de errores y simplificar el código, Rust incluye un operador especial: el operador de propagación `?`. Este operador es increíblemente útil para trabajar con estos tipos, ya que permite simplificar la lógica de manejo de errores y evitar la necesidad de escribir código de control repetitivo. + +### ¿Qué es el operador `?` + +El operador de propagación `?` te permite escribir código más limpio y legible al manejar valores de `Option` o `Result`. En lugar de tener que utilizar explícitamente pattern matching o combinadores como `and_then` o `unwrap`, el operador `?` propaga automáticamente el error o la falta de un valor si ocurre, de modo que la ejecución del programa se detiene y el error se devuelve inmediatamente. + +### Usando `?` con `Result` + +El caso más común de uso del operador `?` es con el tipo `Result`. Cuando lo aplicas a un `Result`, si la operación devuelve un `Err`, el operador detiene la ejecución y propaga el error hacia arriba. Si el valor es un `Ok`, entonces el operador extrae el valor y continúa la ejecución. + +#### Ejemplo básico de uso con `Result` + +```rust +use std::fs::File; +use std::io::{self, Read}; + +fn leer_archivo(path: &str) -> Result { + let mut archivo = File::open(path)?; // Propaga el error si falla la apertura del archivo + let mut contenido = String::new(); + archivo.read_to_string(&mut contenido)?; // Propaga el error si falla la lectura + Ok(contenido) +} + +fn main() { + match leer_archivo("archivo.txt") { + Ok(contenido) => println!("Contenido: {}", contenido), + Err(error) => println!("No se pudo leer el archivo: {}", error), + } +} +``` + +En este ejemplo, en lugar de tener que manejar cada posible error con `match` o `unwrap`, el operador `?` simplifica el flujo al propagar automáticamente el error en caso de que ocurra, devolviendo un `Err` al llamador si alguna de las operaciones falla. + +#### Detalles importantes sobre `Result` y `?` + +- El operador `?` solo puede usarse dentro de funciones que devuelven un `Result`. Si lo usas en una función que no devuelve un `Result`, obtendrás un error de compilación. +- Si usas el operador `?` en una función que devuelve otro tipo de error, puedes convertir el error con la función `From`. + +```rust +fn abrir_archivo(path: &str) -> Result { + let archivo = File::open(path).map_err(|_| "Error al abrir el archivo".to_string())?; + Ok(archivo) +} +``` + +### Usando `?` con `Option` + +El operador `?` también funciona con el tipo `Option`. Cuando lo aplicas a un `Option`, si el valor es `None`, propaga el `None` hacia arriba y detiene la ejecución de la función. Si es `Some`, extrae el valor y continúa. + +#### Ejemplo básico de uso con `Option` + +```rust +fn obtener_valor(data: Option) -> Option { + let valor = data?; // Propaga None si el valor es None + Some(valor * 2) +} + +fn main() { + let data = Some(10); + let resultado = obtener_valor(data); + println!("{:?}", resultado); // Imprime: Some(20) + + let none_data: Option = None; + let resultado_none = obtener_valor(none_data); + println!("{:?}", resultado_none); // Imprime: None +} +``` + +En este caso, si `data` es `None`, la función `obtener_valor` devuelve inmediatamente `None`, sin necesidad de realizar más comprobaciones. Si el valor es `Some`, el operador `?` extrae el valor y continúa con la operación. + +### Uso combinado con otros tipos + +El operador `?` puede ser utilizado junto con combinadores y otras técnicas de manejo de errores, permitiendo simplificar aún más el código. También puedes encadenar múltiples operaciones con `Result` o `Option` utilizando `?` para un flujo claro y conciso. + +#### Ejemplo con múltiples operaciones `Result` + +```rust +use std::fs::File; +use std::io::{self, Read, Write}; + +fn copiar_contenido(origen: &str, destino: &str) -> Result<(), io::Error> { + let mut archivo_origen = File::open(origen)?; + let mut contenido = String::new(); + archivo_origen.read_to_string(&mut contenido)?; + + let mut archivo_destino = File::create(destino)?; + archivo_destino.write_all(contenido.as_bytes())?; + + Ok(()) +} + +fn main() { + match copiar_contenido("origen.txt", "destino.txt") { + Ok(()) => println!("Contenido copiado con éxito"), + Err(error) => println!("Error al copiar el contenido: {}", error), + } +} +``` + +En este ejemplo, se combinan varias operaciones que podrían fallar, como abrir, leer y escribir archivos. El operador `?` garantiza que cualquier error en estas operaciones se propague automáticamente hacia arriba, lo que simplifica enormemente la gestión del flujo de control. + +### Coste Computacional + +El uso del operador `?` no añade ningún coste significativo en términos de rendimiento. Al ser una herramienta que simplemente descompone enums (`Result` y `Option`) en su representación interna, permite que el código sea más conciso y fácil de seguir sin sacrificar eficiencia. Además, dado que el control de errores es explícito y seguro, Rust optimiza este tipo de operaciones de manera que el coste computacional es mínimo. + +### Conclusión + +El operador `?` en Rust es una herramienta poderosa para simplificar el manejo de errores y valores opcionales cuando trabajas con `Result` y `Option`. Al eliminar la necesidad de un control de errores manual en cada operación, permite que tu código sea más legible, menos propenso a errores y mucho más limpio. Al mismo tiempo, Rust asegura que este operador se implemente de manera eficiente, sin sacrificar rendimiento ni seguridad. + +Gracias a este operador, manejar errores en Rust se convierte en una tarea sencilla y controlada, sin recurrir a excepciones o técnicas que podrían generar comportamientos impredecibles. From 69e980e30ad25ed4b0fb21d20eabbb49b733ea8f Mon Sep 17 00:00:00 2001 From: Sergio Ribera <56278796+SergioRibera@users.noreply.github.com> Date: Sun, 8 Sep 2024 17:31:16 -0400 Subject: [PATCH 6/7] feat: add custom error --- content/3.error-handling/2.result.md | 8 +- content/3.error-handling/3.operator.md | 137 -------------- .../3.propagation-operator.md | 179 ++++++++++++++++++ content/3.error-handling/4.custom-errors.md | 179 ++++++++++++++++++ 4 files changed, 362 insertions(+), 141 deletions(-) delete mode 100644 content/3.error-handling/3.operator.md create mode 100644 content/3.error-handling/3.propagation-operator.md create mode 100644 content/3.error-handling/4.custom-errors.md diff --git a/content/3.error-handling/2.result.md b/content/3.error-handling/2.result.md index 6c98b13..5d1a0d2 100644 --- a/content/3.error-handling/2.result.md +++ b/content/3.error-handling/2.result.md @@ -13,12 +13,12 @@ data: - name: 'Libro Oficial' english: false link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum' - - name: 'Documentacion Oficial' - english: false - link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html' - name: 'Comprehensive Rust' + english: false + link: 'https://google.github.io/comprehensive-rust/es/std-types/result.html' + - name: 'Documentacion Oficial' english: true - link: 'https://doc.rust-lang.org/std/option' + link: 'https://doc.rust-lang.org/stable/std/result' - name: '¿Cómo almacena Rust los enum en memoria?' english: false link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria' diff --git a/content/3.error-handling/3.operator.md b/content/3.error-handling/3.operator.md deleted file mode 100644 index 5ed240e..0000000 --- a/content/3.error-handling/3.operator.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -title: 'Operador de Propagación (`?`)' -description: 'Mejorando el manejo de errores con el Operador de Propagación (`?`)' -draft: true -data: - type: 'custom' - topicLevel: 'start' - position: - x: 255 - y: 520 - width: 320 - externalLinks: - - name: 'Libro Oficial' - english: false - link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum' - - name: 'Documentacion Oficial' - english: false - link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html' - - name: 'Comprehensive Rust' - english: true - link: 'https://doc.rust-lang.org/std/option' - - name: '¿Cómo almacena Rust los enum en memoria?' - english: false - link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria' ---- -## Uso del Operador de Propagación (`?`) en Rust con `Option` y `Result` - -Rust ofrece un enfoque único y eficiente para manejar errores y valores opcionales mediante los tipos `Option` y `Result`. Para facilitar la propagación de errores y simplificar el código, Rust incluye un operador especial: el operador de propagación `?`. Este operador es increíblemente útil para trabajar con estos tipos, ya que permite simplificar la lógica de manejo de errores y evitar la necesidad de escribir código de control repetitivo. - -### ¿Qué es el operador `?` - -El operador de propagación `?` te permite escribir código más limpio y legible al manejar valores de `Option` o `Result`. En lugar de tener que utilizar explícitamente pattern matching o combinadores como `and_then` o `unwrap`, el operador `?` propaga automáticamente el error o la falta de un valor si ocurre, de modo que la ejecución del programa se detiene y el error se devuelve inmediatamente. - -### Usando `?` con `Result` - -El caso más común de uso del operador `?` es con el tipo `Result`. Cuando lo aplicas a un `Result`, si la operación devuelve un `Err`, el operador detiene la ejecución y propaga el error hacia arriba. Si el valor es un `Ok`, entonces el operador extrae el valor y continúa la ejecución. - -#### Ejemplo básico de uso con `Result` - -```rust -use std::fs::File; -use std::io::{self, Read}; - -fn leer_archivo(path: &str) -> Result { - let mut archivo = File::open(path)?; // Propaga el error si falla la apertura del archivo - let mut contenido = String::new(); - archivo.read_to_string(&mut contenido)?; // Propaga el error si falla la lectura - Ok(contenido) -} - -fn main() { - match leer_archivo("archivo.txt") { - Ok(contenido) => println!("Contenido: {}", contenido), - Err(error) => println!("No se pudo leer el archivo: {}", error), - } -} -``` - -En este ejemplo, en lugar de tener que manejar cada posible error con `match` o `unwrap`, el operador `?` simplifica el flujo al propagar automáticamente el error en caso de que ocurra, devolviendo un `Err` al llamador si alguna de las operaciones falla. - -#### Detalles importantes sobre `Result` y `?` - -- El operador `?` solo puede usarse dentro de funciones que devuelven un `Result`. Si lo usas en una función que no devuelve un `Result`, obtendrás un error de compilación. -- Si usas el operador `?` en una función que devuelve otro tipo de error, puedes convertir el error con la función `From`. - -```rust -fn abrir_archivo(path: &str) -> Result { - let archivo = File::open(path).map_err(|_| "Error al abrir el archivo".to_string())?; - Ok(archivo) -} -``` - -### Usando `?` con `Option` - -El operador `?` también funciona con el tipo `Option`. Cuando lo aplicas a un `Option`, si el valor es `None`, propaga el `None` hacia arriba y detiene la ejecución de la función. Si es `Some`, extrae el valor y continúa. - -#### Ejemplo básico de uso con `Option` - -```rust -fn obtener_valor(data: Option) -> Option { - let valor = data?; // Propaga None si el valor es None - Some(valor * 2) -} - -fn main() { - let data = Some(10); - let resultado = obtener_valor(data); - println!("{:?}", resultado); // Imprime: Some(20) - - let none_data: Option = None; - let resultado_none = obtener_valor(none_data); - println!("{:?}", resultado_none); // Imprime: None -} -``` - -En este caso, si `data` es `None`, la función `obtener_valor` devuelve inmediatamente `None`, sin necesidad de realizar más comprobaciones. Si el valor es `Some`, el operador `?` extrae el valor y continúa con la operación. - -### Uso combinado con otros tipos - -El operador `?` puede ser utilizado junto con combinadores y otras técnicas de manejo de errores, permitiendo simplificar aún más el código. También puedes encadenar múltiples operaciones con `Result` o `Option` utilizando `?` para un flujo claro y conciso. - -#### Ejemplo con múltiples operaciones `Result` - -```rust -use std::fs::File; -use std::io::{self, Read, Write}; - -fn copiar_contenido(origen: &str, destino: &str) -> Result<(), io::Error> { - let mut archivo_origen = File::open(origen)?; - let mut contenido = String::new(); - archivo_origen.read_to_string(&mut contenido)?; - - let mut archivo_destino = File::create(destino)?; - archivo_destino.write_all(contenido.as_bytes())?; - - Ok(()) -} - -fn main() { - match copiar_contenido("origen.txt", "destino.txt") { - Ok(()) => println!("Contenido copiado con éxito"), - Err(error) => println!("Error al copiar el contenido: {}", error), - } -} -``` - -En este ejemplo, se combinan varias operaciones que podrían fallar, como abrir, leer y escribir archivos. El operador `?` garantiza que cualquier error en estas operaciones se propague automáticamente hacia arriba, lo que simplifica enormemente la gestión del flujo de control. - -### Coste Computacional - -El uso del operador `?` no añade ningún coste significativo en términos de rendimiento. Al ser una herramienta que simplemente descompone enums (`Result` y `Option`) en su representación interna, permite que el código sea más conciso y fácil de seguir sin sacrificar eficiencia. Además, dado que el control de errores es explícito y seguro, Rust optimiza este tipo de operaciones de manera que el coste computacional es mínimo. - -### Conclusión - -El operador `?` en Rust es una herramienta poderosa para simplificar el manejo de errores y valores opcionales cuando trabajas con `Result` y `Option`. Al eliminar la necesidad de un control de errores manual en cada operación, permite que tu código sea más legible, menos propenso a errores y mucho más limpio. Al mismo tiempo, Rust asegura que este operador se implemente de manera eficiente, sin sacrificar rendimiento ni seguridad. - -Gracias a este operador, manejar errores en Rust se convierte en una tarea sencilla y controlada, sin recurrir a excepciones o técnicas que podrían generar comportamientos impredecibles. diff --git a/content/3.error-handling/3.propagation-operator.md b/content/3.error-handling/3.propagation-operator.md new file mode 100644 index 0000000..44d77b8 --- /dev/null +++ b/content/3.error-handling/3.propagation-operator.md @@ -0,0 +1,179 @@ +--- +title: 'Operador de Propagación (`?`)' +description: 'Mejorando el manejo de errores con el Operador de Propagación (`?`)' +draft: true +data: + type: 'custom' + topicLevel: 'start' + position: + x: 255 + y: 520 + width: 320 + externalLinks: + - name: 'Libro Oficial' + english: false + link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum' + - name: 'Documentacion Oficial' + english: false + link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html' + - name: 'Comprehensive Rust' + english: true + link: 'https://doc.rust-lang.org/std/option' + - name: '¿Cómo almacena Rust los enum en memoria?' + english: false + link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria' +--- +## Creando Tus Propios Errores en Rust: Buenas Prácticas y Herramientas + +El manejo de errores en Rust es fundamental para construir aplicaciones seguras y eficientes. Aunque `Result` y `Option` cubren la mayoría de los casos, cuando desarrollas bibliotecas o aplicaciones más complejas, es común que necesites crear tus propios errores personalizados. En este post, te guiaré por las mejores prácticas para crear tus propios errores en Rust, destacando el uso de enumeradores, las limitaciones de `Box`, y cómo mejorar tu código con crates como `thiserror`, `anyhow` y `eyre`. + +### ¿Por qué crear tus propios errores? + +Rust fomenta el manejo explícito de errores mediante el uso de `Result` y `Option`. En muchos casos, el error que quieres propagar no está cubierto por los tipos estándar como `std::io::Error` o `std::fmt::Error`, por lo que crear tus propios tipos de error te permite: + +1. **Especificar el contexto exacto del fallo**. +2. **Incluir variantes para distintos tipos de errores**. +3. **Proporcionar mejores mensajes de error**. +4. **Asegurarte de que el manejo de errores sea parte de la lógica del flujo de tu aplicación**. + +### Creando Errores con `enum` + +El enfoque recomendado para crear errores personalizados en Rust es usar un `enum`. Un `enum` puede representar diferentes variantes de error que pueden ocurrir en tu programa o biblioteca. Esto te permite manejar distintos tipos de errores de forma estructurada, con la ventaja de que el compilador te obliga a tratar todos los casos. + +Aquí tienes un ejemplo básico: + +```rust +use std::fmt; + +#[derive(Debug)] +enum MyError { + NotFound, + InvalidInput(String), + IoError(std::io::Error), +} + +impl fmt::Display for MyError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MyError::NotFound => write!(f, "Recurso no encontrado"), + MyError::InvalidInput(msg) => write!(f, "Entrada inválida: {}", msg), + MyError::IoError(e) => write!(f, "Error de IO: {}", e), + } + } +} + +impl std::error::Error for MyError {} + +fn main() -> Result<(), MyError> { + // Simulamos un error + Err(MyError::NotFound) +} +``` + +En este ejemplo: + +- `MyError` puede representar diferentes errores (`NotFound`, `InvalidInput` y `IoError`). +- Implementamos `Display` para personalizar el mensaje de error y `std::error::Error` para integrarnos con el sistema de errores de Rust. + +### Por Qué Evitar `Box` + +Una alternativa común es usar `Box` para empaquetar errores. Esto permite la creación de errores dinámicos en tiempo de ejecución. Sin embargo, **esto no es recomendado**, ya que sacrifica el control estático que proporciona el sistema de tipos. Además, el uso de `Box` tiene un coste en rendimiento, ya que introduce asignaciones en el heap y elimina la capacidad de optimización en tiempo de compilación. + +Por ejemplo: + +```rust +fn error_con_box() -> Result<(), Box> { + let io_error = std::fs::File::open("archivo_inexistente.txt")?; + Ok(()) +} +``` + +Aunque `Box` es flexible, oculta la verdadera naturaleza de los errores que pueden ocurrir, lo que complica el manejo en el código llamador. + +### Mejorando el Manejo de Errores con `thiserror` + +Para evitar el tedio de implementar manualmente `Display`, `From`, y otras interfaces para tus errores, puedes usar el crate [`thiserror`](https://docs.rs/thiserror/latest/thiserror/). `thiserror` simplifica la creación de errores personalizados al generar automáticamente el código boilerplate, manteniendo tu código más limpio. + +Aquí tienes el mismo ejemplo anterior usando `thiserror`: + +```rust +use thiserror::Error; + +#[derive(Error, Debug)] +enum MyError { + #[error("Recurso no encontrado")] + NotFound, + + #[error("Entrada inválida: {0}")] + InvalidInput(String), + + #[error(transparent)] + IoError(#[from] std::io::Error), +} + +fn main() -> Result<(), MyError> { + // Simulamos un error + Err(MyError::NotFound) +} +``` + +### Ventajas de `thiserror`: + +1. **Menos boilerplate:** No necesitas escribir manualmente implementaciones de `Display` o `From`. +2. **Uso de atributos:** Puedes usar atributos para personalizar los mensajes de error y para manejar automáticamente la conversión de errores (como `#[from]`). +3. **Mejor mantenimiento:** Al eliminar el código repetitivo, tu código se vuelve más legible y fácil de mantener. + +### Uso de `anyhow` y `eyre` para Errores Genéricos + +Si necesitas manejar errores de manera más flexible y no te importa tanto el tipo específico del error (por ejemplo, en aplicaciones CLI o proyectos rápidos), puedes usar el crate [`anyhow`](https://docs.rs/anyhow/latest/anyhow/) o su contraparte personalizable [`eyre`](https://docs.rs/color-eyre/latest/color-eyre/). Estos crates proporcionan tipos de error genéricos y facilitan el manejo de errores de una manera más sencilla, pero sin perder información útil. + +#### Ejemplo con `anyhow`: + +```rust +use anyhow::{Result, Context}; + +fn funcion_con_error() -> Result<()> { + let _file = std::fs::File::open("archivo.txt") + .with_context(|| "No se pudo abrir el archivo")?; + Ok(()) +} + +fn main() -> Result<()> { + funcion_con_error()?; + Ok(()) +} +``` + +En este ejemplo: + +- `anyhow::Result` es un alias conveniente para `Result`. +- `with_context()` proporciona mensajes de error adicionales, lo que facilita el diagnóstico de fallos. + +#### Ejemplo con `eyre` y Errores Coloreados + +`eyre` permite un manejo de errores similar a `anyhow`, pero con la capacidad de agregar "reportes" de errores enriquecidos y con colores, ideales para la salida de errores en la terminal: + +```rust +use color_eyre::eyre::Result; + +fn main() -> Result<()> { + color_eyre::install()?; // Habilita los reportes coloreados + + let _file = std::fs::File::open("archivo.txt")?; + Ok(()) +} +``` + +### Comparativa de Opciones + +| **Método** | **Ventajas** | **Desventajas** | +|----------------------------|------------------------------------------------|--------------------------------------------| +| **Enum manual** | Control preciso, tipado estático | Mucho código repetitivo | +| **`Box`** | Flexibilidad para manejar cualquier error | Oculta la naturaleza del error, más lento | +| **`thiserror`** | Fácil de usar, sin boilerplate, mantiene tipos | Menos flexible que `Box` | +| **`anyhow`** | Simplicidad en el manejo de errores genéricos | Pierdes detalles sobre el tipo de error | +| **`eyre`** | Reportes detallados y coloreados | Similar a `anyhow` en términos de flexibilidad | + +### Conclusión + +Crear tus propios errores en Rust es una parte crucial de escribir código seguro y robusto. Usar `enum` te proporciona el máximo control sobre el manejo de errores, mientras que herramientas como `thiserror` y `anyhow` te permiten reducir el código repetitivo y mejorar la legibilidad. Dependiendo del contexto de tu aplicación, puedes elegir entre un enfoque más tipado o uno más flexible. En cualquier caso, Rust proporciona las herramientas necesarias para garantizar que los errores sean manejados de manera segura y eficiente. diff --git a/content/3.error-handling/4.custom-errors.md b/content/3.error-handling/4.custom-errors.md new file mode 100644 index 0000000..f5842d9 --- /dev/null +++ b/content/3.error-handling/4.custom-errors.md @@ -0,0 +1,179 @@ +--- +title: 'Errores Personalizados' +description: 'Creando Tus Propios Errores en Rust: Buenas Prácticas y Herramientas' +draft: true +data: + type: 'custom' + topicLevel: 'medium' + position: + x: 650 + y: 740 + width: 320 + externalLinks: + - name: 'Libro Oficial' + english: false + link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum' + - name: 'Documentacion Oficial' + english: false + link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html' + - name: 'Comprehensive Rust' + english: true + link: 'https://doc.rust-lang.org/std/option' + - name: '¿Cómo almacena Rust los enum en memoria?' + english: false + link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria' +--- +## Creando Tus Propios Errores en Rust: Buenas Prácticas y Herramientas + +El manejo de errores en Rust es fundamental para construir aplicaciones seguras y eficientes. Aunque `Result` y `Option` cubren la mayoría de los casos, cuando desarrollas bibliotecas o aplicaciones más complejas, es común que necesites crear tus propios errores personalizados. En este post, te guiaré por las mejores prácticas para crear tus propios errores en Rust, destacando el uso de enumeradores, las limitaciones de `Box`, y cómo mejorar tu código con crates como `thiserror`, `anyhow` y `eyre`. + +### ¿Por qué crear tus propios errores? + +Rust fomenta el manejo explícito de errores mediante el uso de `Result` y `Option`. En muchos casos, el error que quieres propagar no está cubierto por los tipos estándar como `std::io::Error` o `std::fmt::Error`, por lo que crear tus propios tipos de error te permite: + +1. **Especificar el contexto exacto del fallo**. +2. **Incluir variantes para distintos tipos de errores**. +3. **Proporcionar mejores mensajes de error**. +4. **Asegurarte de que el manejo de errores sea parte de la lógica del flujo de tu aplicación**. + +### Creando Errores con `enum` + +El enfoque recomendado para crear errores personalizados en Rust es usar un `enum`. Un `enum` puede representar diferentes variantes de error que pueden ocurrir en tu programa o biblioteca. Esto te permite manejar distintos tipos de errores de forma estructurada, con la ventaja de que el compilador te obliga a tratar todos los casos. + +Aquí tienes un ejemplo básico: + +```rust +use std::fmt; + +#[derive(Debug)] +enum MyError { + NotFound, + InvalidInput(String), + IoError(std::io::Error), +} + +impl fmt::Display for MyError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MyError::NotFound => write!(f, "Recurso no encontrado"), + MyError::InvalidInput(msg) => write!(f, "Entrada inválida: {}", msg), + MyError::IoError(e) => write!(f, "Error de IO: {}", e), + } + } +} + +impl std::error::Error for MyError {} + +fn main() -> Result<(), MyError> { + // Simulamos un error + Err(MyError::NotFound) +} +``` + +En este ejemplo: + +- `MyError` puede representar diferentes errores (`NotFound`, `InvalidInput` y `IoError`). +- Implementamos `Display` para personalizar el mensaje de error y `std::error::Error` para integrarnos con el sistema de errores de Rust. + +### Por Qué Evitar `Box` + +Una alternativa común es usar `Box` para empaquetar errores. Esto permite la creación de errores dinámicos en tiempo de ejecución. Sin embargo, **esto no es recomendado**, ya que sacrifica el control estático que proporciona el sistema de tipos. Además, el uso de `Box` tiene un coste en rendimiento, ya que introduce asignaciones en el heap y elimina la capacidad de optimización en tiempo de compilación. + +Por ejemplo: + +```rust +fn error_con_box() -> Result<(), Box> { + let io_error = std::fs::File::open("archivo_inexistente.txt")?; + Ok(()) +} +``` + +Aunque `Box` es flexible, oculta la verdadera naturaleza de los errores que pueden ocurrir, lo que complica el manejo en el código llamador. + +### Mejorando el Manejo de Errores con `thiserror` + +Para evitar el tedio de implementar manualmente `Display`, `From`, y otras interfaces para tus errores, puedes usar el crate [`thiserror`](https://docs.rs/thiserror/latest/thiserror/). `thiserror` simplifica la creación de errores personalizados al generar automáticamente el código boilerplate, manteniendo tu código más limpio. + +Aquí tienes el mismo ejemplo anterior usando `thiserror`: + +```rust +use thiserror::Error; + +#[derive(Error, Debug)] +enum MyError { + #[error("Recurso no encontrado")] + NotFound, + + #[error("Entrada inválida: {0}")] + InvalidInput(String), + + #[error(transparent)] + IoError(#[from] std::io::Error), +} + +fn main() -> Result<(), MyError> { + // Simulamos un error + Err(MyError::NotFound) +} +``` + +### Ventajas de `thiserror`: + +1. **Menos boilerplate:** No necesitas escribir manualmente implementaciones de `Display` o `From`. +2. **Uso de atributos:** Puedes usar atributos para personalizar los mensajes de error y para manejar automáticamente la conversión de errores (como `#[from]`). +3. **Mejor mantenimiento:** Al eliminar el código repetitivo, tu código se vuelve más legible y fácil de mantener. + +### Uso de `anyhow` y `eyre` para Errores Genéricos + +Si necesitas manejar errores de manera más flexible y no te importa tanto el tipo específico del error (por ejemplo, en aplicaciones CLI o proyectos rápidos), puedes usar el crate [`anyhow`](https://docs.rs/anyhow/latest/anyhow/) o su contraparte personalizable [`eyre`](https://docs.rs/color-eyre/latest/color-eyre/). Estos crates proporcionan tipos de error genéricos y facilitan el manejo de errores de una manera más sencilla, pero sin perder información útil. + +#### Ejemplo con `anyhow`: + +```rust +use anyhow::{Result, Context}; + +fn funcion_con_error() -> Result<()> { + let _file = std::fs::File::open("archivo.txt") + .with_context(|| "No se pudo abrir el archivo")?; + Ok(()) +} + +fn main() -> Result<()> { + funcion_con_error()?; + Ok(()) +} +``` + +En este ejemplo: + +- `anyhow::Result` es un alias conveniente para `Result`. +- `with_context()` proporciona mensajes de error adicionales, lo que facilita el diagnóstico de fallos. + +#### Ejemplo con `eyre` y Errores Coloreados + +`eyre` permite un manejo de errores similar a `anyhow`, pero con la capacidad de agregar "reportes" de errores enriquecidos y con colores, ideales para la salida de errores en la terminal: + +```rust +use color_eyre::eyre::Result; + +fn main() -> Result<()> { + color_eyre::install()?; // Habilita los reportes coloreados + + let _file = std::fs::File::open("archivo.txt")?; + Ok(()) +} +``` + +### Comparativa de Opciones + +| **Método** | **Ventajas** | **Desventajas** | +|----------------------------|-----------------------------------------------|--------------------------------------------| +| **Enum manual** | Control preciso, tipado estático | Mucho código repetitivo | +| **`Box`** | Flexibilidad para manejar cualquier error | Oculta la naturaleza del error, más lento | +| **`thiserror`** | Fácil de usar, sin boilerplate, mantiene tipos | Menos flexible que `Box` | +| **`anyhow`** | Simplicidad en el manejo de errores genéricos | Pierdes detalles sobre el tipo de error | +| **`eyre`** | Reportes detallados y coloreados | Similar a `anyhow` en términos de flexibilidad | + +### Conclusión + +Crear tus propios errores en Rust es una parte crucial de escribir código seguro y robusto. Usar `enum` te proporciona el máximo control sobre el manejo de errores, mientras que herramientas como `thiserror` y `anyhow` te permiten reducir el código repetitivo y mejorar la legibilidad. Dependiendo del contexto de tu aplicación, puedes elegir entre un enfoque más tipado o uno más flexible. En cualquier caso, Rust proporciona las herramientas necesarias para garantizar que los errores sean manejados de manera segura y eficiente. From eb0c99d49b491651efac9f6efcf7e526ce21dbf1 Mon Sep 17 00:00:00 2001 From: Sergio Ribera <56278796+SergioRibera@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:07:54 -0400 Subject: [PATCH 7/7] feat: fix positions and details --- content/3.error-handling/1.option.md | 12 ++++++------ content/3.error-handling/2.result.md | 8 +++++--- content/3.error-handling/3.propagation-operator.md | 8 +++++--- content/3.error-handling/4.custom-errors.md | 12 +++--------- content/3.error-handling/index.yml | 10 +++++----- content/4.cargo/index.md | 6 +++--- 6 files changed, 27 insertions(+), 29 deletions(-) diff --git a/content/3.error-handling/1.option.md b/content/3.error-handling/1.option.md index 3be3df8..a4553e1 100644 --- a/content/3.error-handling/1.option.md +++ b/content/3.error-handling/1.option.md @@ -6,19 +6,19 @@ data: type: 'custom' topicLevel: 'start' position: - x: 255 - y: 520 + x: 320 + y: 580 width: 320 externalLinks: - name: 'Libro Oficial' english: false link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum' - - name: 'Documentacion Oficial' + - name: 'Comprehensive Rust' english: false link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html' - - name: 'Comprehensive Rust' + - name: 'Documentacion Oficial' english: true - link: 'https://doc.rust-lang.org/std/option' + link: 'https://doc.rust-lang.org/stable/std/option' - name: '¿Cómo almacena Rust los enum en memoria?' english: false link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria' @@ -46,7 +46,7 @@ enum Option { Rust ofrece múltiples funciones para manipular opciones de forma segura: - **is_some() e is_none():** Verifican si un `Option` contiene un valor o no. - + ```rust let maybe_value: Option = Some(5); assert!(maybe_value.is_some()); diff --git a/content/3.error-handling/2.result.md b/content/3.error-handling/2.result.md index 5d1a0d2..6c368fb 100644 --- a/content/3.error-handling/2.result.md +++ b/content/3.error-handling/2.result.md @@ -1,14 +1,16 @@ --- -title: 'Results' +title: 'Result' description: 'Result es una enumeración en Rust que se utiliza para representar valores que pueden fallar' draft: true data: type: 'custom' topicLevel: 'start' position: - x: 255 - y: 520 + x: 320 + y: 620 width: 320 + sourcePosition: + error-handling: 'bottom' externalLinks: - name: 'Libro Oficial' english: false diff --git a/content/3.error-handling/3.propagation-operator.md b/content/3.error-handling/3.propagation-operator.md index 44d77b8..b122728 100644 --- a/content/3.error-handling/3.propagation-operator.md +++ b/content/3.error-handling/3.propagation-operator.md @@ -4,11 +4,13 @@ description: 'Mejorando el manejo de errores con el Operador de Propagación (`? draft: true data: type: 'custom' - topicLevel: 'start' + topicLevel: 'medium' position: - x: 255 - y: 520 + x: 650 + y: 700 width: 320 + sourcePosition: + error-handling: 'left' externalLinks: - name: 'Libro Oficial' english: false diff --git a/content/3.error-handling/4.custom-errors.md b/content/3.error-handling/4.custom-errors.md index f5842d9..e32e117 100644 --- a/content/3.error-handling/4.custom-errors.md +++ b/content/3.error-handling/4.custom-errors.md @@ -10,18 +10,12 @@ data: y: 740 width: 320 externalLinks: - - name: 'Libro Oficial' + - name: 'Comprehensive Rust' english: false - link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum' + link: 'https://google.github.io/comprehensive-rust/es/error-handling/error.html' - name: 'Documentacion Oficial' - english: false - link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html' - - name: 'Comprehensive Rust' english: true - link: 'https://doc.rust-lang.org/std/option' - - name: '¿Cómo almacena Rust los enum en memoria?' - english: false - link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria' + link: 'https://doc.rust-lang.org/stable/std/error/trait.Error.html' --- ## Creando Tus Propios Errores en Rust: Buenas Prácticas y Herramientas diff --git a/content/3.error-handling/index.yml b/content/3.error-handling/index.yml index 4c9a8dc..72551bb 100644 --- a/content/3.error-handling/index.yml +++ b/content/3.error-handling/index.yml @@ -1,4 +1,3 @@ ---- title: 'Manejo de Errores' description: '' draft: true @@ -6,10 +5,11 @@ data: type: 'custom' topicLevel: 'medium' position: - x: 300 - y: 600 + x: 390 + y: 700 sourcePosition: basic: 'left' - targetPosition: + targetPosition: + result: 'top' cargo: 'bottom' ---- + propagation-operator: 'right' diff --git a/content/4.cargo/index.md b/content/4.cargo/index.md index 330de6c..4aa4f4b 100644 --- a/content/4.cargo/index.md +++ b/content/4.cargo/index.md @@ -7,10 +7,10 @@ data: topicLevel: 'start' position: x: 200 - y: 700 + y: 750 sourcePosition: - error-handling: 'top' - targetPosition: + error-handling: 'right' + targetPosition: traits: 'bottom' --- # Titulo