Skip to content

Commit ae96fbe

Browse files
committed
feat: add error operator
1 parent 66bdffb commit ae96fbe

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
---
2+
title: 'Operador de Propagación (`?`)'
3+
description: 'Mejorando el manejo de errores con el Operador de Propagación (`?`)'
4+
draft: true
5+
data:
6+
type: 'custom'
7+
topicLevel: 'start'
8+
position:
9+
x: 255
10+
y: 520
11+
width: 320
12+
externalLinks:
13+
- name: 'Libro Oficial'
14+
english: false
15+
link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum'
16+
- name: 'Documentacion Oficial'
17+
english: false
18+
link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html'
19+
- name: 'Comprehensive Rust'
20+
english: true
21+
link: 'https://doc.rust-lang.org/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'
25+
---
26+
## Uso del Operador de Propagación (`?`) en Rust con `Option` y `Result`
27+
28+
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.
29+
30+
### ¿Qué es el operador `?`
31+
32+
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.
33+
34+
### Usando `?` con `Result`
35+
36+
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.
37+
38+
#### Ejemplo básico de uso con `Result`
39+
40+
```rust
41+
use std::fs::File;
42+
use std::io::{self, Read};
43+
44+
fn leer_archivo(path: &str) -> Result<String, io::Error> {
45+
let mut archivo = File::open(path)?; // Propaga el error si falla la apertura del archivo
46+
let mut contenido = String::new();
47+
archivo.read_to_string(&mut contenido)?; // Propaga el error si falla la lectura
48+
Ok(contenido)
49+
}
50+
51+
fn main() {
52+
match leer_archivo("archivo.txt") {
53+
Ok(contenido) => println!("Contenido: {}", contenido),
54+
Err(error) => println!("No se pudo leer el archivo: {}", error),
55+
}
56+
}
57+
```
58+
59+
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.
60+
61+
#### Detalles importantes sobre `Result` y `?`
62+
63+
- 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.
64+
- Si usas el operador `?` en una función que devuelve otro tipo de error, puedes convertir el error con la función `From`.
65+
66+
```rust
67+
fn abrir_archivo(path: &str) -> Result<File, String> {
68+
let archivo = File::open(path).map_err(|_| "Error al abrir el archivo".to_string())?;
69+
Ok(archivo)
70+
}
71+
```
72+
73+
### Usando `?` con `Option`
74+
75+
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.
76+
77+
#### Ejemplo básico de uso con `Option`
78+
79+
```rust
80+
fn obtener_valor(data: Option<i32>) -> Option<i32> {
81+
let valor = data?; // Propaga None si el valor es None
82+
Some(valor * 2)
83+
}
84+
85+
fn main() {
86+
let data = Some(10);
87+
let resultado = obtener_valor(data);
88+
println!("{:?}", resultado); // Imprime: Some(20)
89+
90+
let none_data: Option<i32> = None;
91+
let resultado_none = obtener_valor(none_data);
92+
println!("{:?}", resultado_none); // Imprime: None
93+
}
94+
```
95+
96+
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.
97+
98+
### Uso combinado con otros tipos
99+
100+
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.
101+
102+
#### Ejemplo con múltiples operaciones `Result`
103+
104+
```rust
105+
use std::fs::File;
106+
use std::io::{self, Read, Write};
107+
108+
fn copiar_contenido(origen: &str, destino: &str) -> Result<(), io::Error> {
109+
let mut archivo_origen = File::open(origen)?;
110+
let mut contenido = String::new();
111+
archivo_origen.read_to_string(&mut contenido)?;
112+
113+
let mut archivo_destino = File::create(destino)?;
114+
archivo_destino.write_all(contenido.as_bytes())?;
115+
116+
Ok(())
117+
}
118+
119+
fn main() {
120+
match copiar_contenido("origen.txt", "destino.txt") {
121+
Ok(()) => println!("Contenido copiado con éxito"),
122+
Err(error) => println!("Error al copiar el contenido: {}", error),
123+
}
124+
}
125+
```
126+
127+
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.
128+
129+
### Coste Computacional
130+
131+
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.
132+
133+
### Conclusión
134+
135+
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.
136+
137+
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.

0 commit comments

Comments
 (0)