Skip to content

Commit 2ed0b45

Browse files
authored
Merge pull request #18 from RustLangES/error_handling
Error handling
2 parents 25aa92a + eb0c99d commit 2ed0b45

File tree

6 files changed

+586
-77
lines changed

6 files changed

+586
-77
lines changed

content/3.error-handling/1.option.md

+71-68
Original file line numberDiff line numberDiff line change
@@ -6,112 +6,115 @@ data:
66
type: 'custom'
77
topicLevel: 'start'
88
position:
9-
x: -700
10-
y: 320
9+
x: 320
10+
y: 580
1111
width: 320
1212
externalLinks:
1313
- name: 'Libro Oficial'
1414
english: false
15-
link: 'https://book.rustlang-es.org/ch03-01-variables-and-mutability#shadowing'
15+
link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum'
1616
- name: 'Comprehensive Rust'
1717
english: false
18-
link: 'https://google.github.io/comprehensive-rust/es/control-flow-basics/blocks-and-scopes.html?highlight=shado#%C3%81mbitos-y--shadowing'
18+
link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html'
19+
- name: 'Documentacion Oficial'
20+
english: true
21+
link: 'https://doc.rust-lang.org/stable/std/option'
22+
- name: '¿Cómo almacena Rust los enum en memoria?'
23+
english: false
24+
link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria'
1925
---
20-
# Option en Rust: Manejo Seguro de Valores Opcionales
26+
## Entendiendo el Tipo `Option` en Rust: Seguridad y Ausencia de Valores Nulos
27+
28+
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.
2129

22-
## Introducción
23-
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
24-
comunes como los de referencias nulas, proporcionando una alternativa robusta y segura para representar valores opcionales. En este
25-
artículo, exploraremos el uso y las ventajas del tipo Option en Rust.
30+
### ¿Qué es un `Option`?
2631

27-
### Concepto de Option en Rust
28-
Option es una enumeración que puede contener un valor (Some(T)) o no (None). Este enfoque asegura que el programador maneje explícitamente
29-
los casos donde un valor puede estar ausente, mejorando así la seguridad y la robustez del código.
32+
`Option` es un enum predefinido en Rust que puede tomar dos valores:
3033

3134
```rust
3235
enum Option<T> {
3336
Some(T),
3437
None,
3538
}
3639
```
37-
### Definición y Uso Básico
3840

39-
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.
40-
Aquí tienes un ejemplo básico:
41+
- `Some(T)` indica que hay un valor presente.
42+
- `None` representa la ausencia de un valor.
4143

42-
```rust
43-
fn find_index(arr: &[i32], target: i32) -> Option<usize> {
44-
for (index, &item) in arr.iter().enumerate() {
45-
if item == target {
46-
return Some(index);
47-
}
48-
}
49-
None
50-
}
51-
```
52-
En este ejemplo, la función find_index devuelve Some(index) si encuentra el target en el arreglo, y None si no lo encuentra.
44+
### Funciones Comunes para Trabajar con `Option`
5345

54-
## Ejemplos de Uso de Option
46+
Rust ofrece múltiples funciones para manipular opciones de forma segura:
5547

56-
### Acceso Seguro a Elementos
57-
Al acceder a elementos en estructuras de datos, Option asegura que manejemos adecuadamente los casos donde los elementos pueden no
58-
existir.
48+
- **is_some() e is_none():** Verifican si un `Option` contiene un valor o no.
5949

60-
```rust
61-
let arr = [1, 2, 3, 4, 5];
62-
let element = arr.get(2); // Devuelve Option<&i32>
50+
```rust
51+
let maybe_value: Option<i32> = Some(5);
52+
assert!(maybe_value.is_some());
6353

64-
match element {
65-
Some(value) => println!("Elemento en el índice 2: {}", value),
66-
None => println!("No hay elemento en el índice 2"),
67-
}
68-
```
54+
let no_value: Option<i32> = None;
55+
assert!(no_value.is_none());
56+
```
6957

70-
### Operaciones que Pueden Fallar
71-
Option se usa en funciones donde una operación puede no tener un resultado válido.
58+
- **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.
7259

73-
```rust
74-
fn divide(a: f64, b: f64) -> Option<f64> {
75-
if b == 0.0 {
76-
None
77-
} else {
78-
Some(a / b)
79-
}
80-
}
81-
```
60+
```rust
61+
let value = maybe_value.unwrap(); // Devuelve 5 o causa un pánico si es None.
62+
```
8263

83-
### Uso de Métodos de Option
84-
Rust proporciona métodos útiles para trabajar con Option, como map, and_then, unwrap_or, entre otros.
64+
- **map():** Permite aplicar una función al valor dentro de un `Option`, devolviendo un nuevo `Option`.
8565

86-
```rust
87-
let some_number = Some(10);
66+
```rust
67+
let maybe_value: Option<i32> = Some(5);
68+
let maybe_double = maybe_value.map(|x| x * 2);
69+
assert_eq!(maybe_double, Some(10));
70+
```
8871

89-
let new_number = some_number.map(|x| x + 1);
72+
- **and(), or() y xor():** Estas funciones permiten combinar opciones de manera segura.
9073

91-
assert_eq!(new_number, Some(11));
92-
```
74+
```rust
75+
let a: Option<i32> = Some(2);
76+
let b: Option<i32> = Some(3);
77+
let c: Option<i32> = None;
78+
79+
assert_eq!(a.and(b), Some(3)); // Devuelve Some(3)
80+
assert_eq!(a.or(c), Some(2)); // Devuelve Some(2)
81+
assert_eq!(c.or(a), Some(2)); // Devuelve Some(2)
82+
```
83+
84+
### Pattern Matching con `Option`
9385

94-
## Beneficios de Option
95-
1.**Seguridad en Tiempo de Compilación:**Option hace que los desarrolladores consideren y manejen explícitamente los casos donde un valor
96-
puede no estar presente, lo que resulta en un código más robusto.
97-
2.**Manejo Explícito de Casos de Ausencia:**Option hace que los desarrolladores consideren y manejen explícitamente los casos donde un
98-
valor puede no estar presente, lo que resulta en un código más robusto.
99-
3.**Compatibilidad con Funciones de Alto Nivel:**Option se integra bien con funciones de alto nivel y características funcionales como
100-
map, and_then, unwrap_or, etc., permitiendo transformaciones y manejos eficientes de valores opcionales.
86+
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`):
10187

102-
## Conclusión
103-
El tipo Option en Rust es una herramienta poderosa para el manejo seguro de valores opcionales. Al eliminar la posibilidad de referencias nulas
104-
y forzar a los desarrolladores a manejar explícitamente los casos de ausencia de valores, Option contribuye significativamente a la
105-
robustez y seguridad del código en Rust. Su uso extensivo en situaciones donde los valores pueden estar presentes o no, junto con sus
106-
métodos y transformaciones funcionales, hacen de Option una parte esencial del ecosistema de Rust.
88+
```rust
89+
let maybe_number = Some(10);
10790

91+
match maybe_number {
92+
Some(value) => println!("El valor es: {}", value),
93+
None => println!("No hay valor"),
94+
}
95+
```
10896

97+
### Interactuar con Múltiples `Option`
10998

99+
Cuando trabajas con múltiples `Option`, puedes combinarlas utilizando combinadores como `and_then()` o emplear pattern matching para manejar múltiples opciones simultáneamente:
110100

101+
```rust
102+
let x: Option<i32> = Some(2);
103+
let y: Option<i32> = Some(3);
111104

105+
let result = x.and_then(|x_val| {
106+
y.map(|y_val| x_val + y_val)
107+
});
112108

109+
assert_eq!(result, Some(5));
110+
```
113111

112+
### Funcionamiento en Memoria
114113

114+
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<T>`. De este modo, `Option` es tan eficiente en memoria como el propio tipo base.
115115

116+
### Conclusión
116117

118+
`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.
117119

120+
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.

content/3.error-handling/2.result.md

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
title: 'Result'
3+
description: 'Result es una enumeración en Rust que se utiliza para representar valores que pueden fallar'
4+
draft: true
5+
data:
6+
type: 'custom'
7+
topicLevel: 'start'
8+
position:
9+
x: 320
10+
y: 620
11+
width: 320
12+
sourcePosition:
13+
error-handling: 'bottom'
14+
externalLinks:
15+
- name: 'Libro Oficial'
16+
english: false
17+
link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum'
18+
- name: 'Comprehensive Rust'
19+
english: false
20+
link: 'https://google.github.io/comprehensive-rust/es/std-types/result.html'
21+
- name: 'Documentacion Oficial'
22+
english: true
23+
link: 'https://doc.rust-lang.org/stable/std/result'
24+
- name: '¿Cómo almacena Rust los enum en memoria?'
25+
english: false
26+
link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria'
27+
---
28+
## El Tipo `Result` en Rust: Manejo Seguro de Errores
29+
30+
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.
31+
32+
### ¿Qué es un `Result`?
33+
34+
`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:
35+
36+
```rust
37+
enum Result<T, E> {
38+
Ok(T),
39+
Err(E),
40+
}
41+
```
42+
43+
- `Ok(T)`: Indica que la operación fue exitosa y contiene un valor del tipo `T`.
44+
- `Err(E)`: Indica que la operación falló y contiene un valor del tipo `E`, que normalmente describe el error.
45+
46+
### Funciones Comunes para Trabajar con `Result`
47+
48+
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:
49+
50+
- **is_ok() e is_err():** Estas funciones permiten verificar si un `Result` contiene un valor exitoso o un error.
51+
52+
```rust
53+
let result: Result<i32, &str> = Ok(10);
54+
assert!(result.is_ok());
55+
56+
let error: Result<i32, &str> = Err("Error!");
57+
assert!(error.is_err());
58+
```
59+
60+
- **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.
61+
62+
```rust
63+
let result: Result<i32, &str> = Ok(5);
64+
let value = result.unwrap(); // Devuelve 5
65+
66+
let error: Result<i32, &str> = Err("Error!");
67+
let value = error.expect("Algo salió mal"); // Causa un pánico con el mensaje proporcionado
68+
```
69+
70+
- **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`.
71+
72+
```rust
73+
let result: Result<i32, &str> = Ok(2);
74+
let doubled = result.map(|x| x * 2);
75+
assert_eq!(doubled, Ok(4));
76+
77+
let error: Result<i32, &str> = Err("Error!");
78+
let new_error = error.map_err(|e| format!("Ocurrió: {}", e));
79+
assert_eq!(new_error, Err("Ocurrió: Error!".to_string()));
80+
```
81+
82+
- **and_then():** Permite encadenar operaciones que también devuelven `Result`, facilitando la propagación de errores.
83+
84+
```rust
85+
let result: Result<i32, &str> = Ok(2);
86+
let chained_result = result.and_then(|x| Ok(x * 3));
87+
assert_eq!(chained_result, Ok(6));
88+
```
89+
90+
### Pattern Matching con `Result`
91+
92+
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:
93+
94+
```rust
95+
let result: Result<i32, &str> = Ok(10);
96+
97+
match result {
98+
Ok(value) => println!("El valor es: {}", value),
99+
Err(error) => println!("Error: {}", error),
100+
}
101+
```
102+
103+
### Interactuar con Múltiples `Result`
104+
105+
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:
106+
107+
```rust
108+
let x: Result<i32, &str> = Ok(2);
109+
let y: Result<i32, &str> = Ok(3);
110+
111+
let result = x.and_then(|x_val| {
112+
y.map(|y_val| x_val + y_val)
113+
});
114+
115+
assert_eq!(result, Ok(5));
116+
```
117+
118+
### Funcionamiento en Memoria
119+
120+
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.
121+
122+
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.
123+
124+
### Comparación con `Option`
125+
126+
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.
127+
128+
### Ejemplo Completo de Uso de `Result`
129+
130+
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:
131+
132+
```rust
133+
use std::fs::File;
134+
use std::io::{self, Read};
135+
136+
fn leer_archivo(path: &str) -> Result<String, io::Error> {
137+
let mut archivo = File::open(path)?;
138+
let mut contenido = String::new();
139+
archivo.read_to_string(&mut contenido)?;
140+
Ok(contenido)
141+
}
142+
143+
fn main() {
144+
match leer_archivo("archivo.txt") {
145+
Ok(contenido) => println!("Contenido: {}", contenido),
146+
Err(error) => println!("No se pudo leer el archivo: {}", error),
147+
}
148+
}
149+
```
150+
151+
### Conclusión
152+
153+
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.

0 commit comments

Comments
 (0)