Enums
## Objetivos de Aprendizaje
- Definir y usar enums
- Dominar el tipo Option
- Trabajar con el tipo Result
- Implementar match con enums
- Comprender la exhaustividad de coincidencia de patrones
## Definiendo Enums
### Enum Basico
```rust
enum Direction {
North,
South,
East,
West,
}
fn main() {
let direction = Direction::North;
match direction {
Direction::North => println!("Heading north"),
Direction::South => println!("Heading south"),
Direction::East => println!("Heading east"),
Direction::West => println!("Heading west"),
}
}
```
### Enum con Datos
```rust
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
fn main() {
let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
let m3 = Message::Write(String::from("hello"));
let m4 = Message::ChangeColor(255, 0, 0);
}
```
### Enum con el Mismo Tipo
```rust
enum IpAddrKind {
V4,
V6,
}
struct IpAddr {
kind: IpAddrKind,
address: String,
}
fn main() {
let home = IpAddr {
kind: IpAddrKind::V4,
address: String::from("127.0.0.1"),
};
}
```
### Metodos de Enum
```rust
impl Message {
fn call(&self) {
match self {
Message::Quit => println!("Quit"),
Message::Move { x, y } => println!("Move to ({}, {})", x, y),
Message::Write(text) => println!("Write: {}", text),
Message::ChangeColor(r, g, b) => println!("Color: {}, {}, {}", r, g, b),
}
}
}
fn main() {
let m = Message::Write(String::from("hello"));
m.call();
}
```
## Enum Option
Option representa valores opcionales (Rust no tiene null):
```rust
enum Option {
Some(T),
None,
}
```
### Usando Option
```rust
fn main() {
let some_number = Some(5);
let no_number: Option = None;
if let Some(n) = some_number {
println!("Number: {}", n);
}
match some_number {
Some(n) => println!("Number: {}", n),
None => println!("No number"),
}
}
```
### Metodos de Option
```rust
fn main() {
let x = Some(5);
// is_some, is_none
println!("{}", x.is_some()); // true
// unwrap_or
let y = x.unwrap_or(0); // 5
// map
let z = x.map(|n| n * 2); // Some(10)
// unwrap (panics si es None)
// let y = None.unwrap(); // Panic!
// unwrap_or_else
let val = Some(5).unwrap_or_else(|| 2 * 3); // 5
let val = (None as Option).unwrap_or_else(|| 2 * 3); // 6
}
```
### Option con Comportamiento similar a null
```rust
fn main() {
let numbers = [1, 2, 3, 4, 5];
// Encontrar primer numero par
let first_even = numbers.iter().find(|&&x| x % 2 == 0);
match first_even {
Some(n) => println!("First even: {}", n),
None => println!("No even number"),
}
// o
if let Some(n) = first_even {
println!("First even: {}", n);
}
}
```
## Enum Result
Result representa sucesso o fracaso:
```rust
enum Result {
Ok(T),
Err(E),
}
```
### Usando Result
```rust
use std::fs::File;
use std::io::Error;
fn main() {
let file = File::open("hello.txt");
match file {
Ok(_) => println!("File opened"),
Err(e) => println!("Error: {:?}", e),
}
}
```
### Metodos de Result
```rust
fn main() {
let x: Result = Ok(5);
// is_ok, is_err
println!("{}", x.is_ok()); // true
// unwrap (panics en Err)
// let y = Err("error").unwrap(); // Panic!
// unwrap_or
let y = x.unwrap_or(0); // 5
// unwrap_or_else
let y = Err("error").unwrap_or_else(|_| 0); // 0
// map
let doubled = x.map(|n| n * 2); // Ok(10)
// map_err
let mapped = x.map_err(|e| format!("Error: {}", e));
}
```
## El Operador ?
```rust
use std::fs::File;
use std::io;
use std::io::Read;
fn read_file() -> Result {
let mut file = File::open("hello.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
```
### ? con Option
```rust
fn first_word(s: &str) -> Option<&str> {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return Some(&s[0..i]);
}
}
None
}
fn main() {
let text = "hello world";
if let Some(word) = first_word(text) {
println!("First word: {}", word);
}
}
```
## Expresiones Match
### Coincidencia Exhaustiva
```rust
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u32 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
```
### Coincidencia con Valores Vinculados
```rust
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
}
fn main() {
let msg = Message::Move { x: 10, y: 20 };
match msg {
Message::Quit => println!("Quit"),
Message::Move { x, y } => println!("Move to ({}, {})", x, y),
Message::Write(text) => println!("Write: {}", text),
}
}
```
### Patrones Catch-all
```rust
fn main() {
let dice_roll = 9;
match dice_roll {
3 => println!("3"),
7 => println!("7"),
other => println!("{}", other), // Catch all
}
match dice_roll {
3 => println!("3"),
7 => println!("7"),
_ => (), // Ignorar el resto
}
}
```
### Combinando Patrones
```rust
fn main() {
let c = 'a';
match c {
'a' | 'e' | 'i' | 'o' | 'u' => println!("vowel"),
'a'..='z' => println!("consonant"),
_ => println!("other"),
}
}
```
## Sintaxis if let
### Patron Unico
```rust
fn main() {
let msg = Message::Move { x: 10, y: 20 };
if let Message::Move { x, y } = msg {
println!("Moving to ({}, {})", x, y);
}
}
```
### if let-else
```rust
fn main() {
let msg = Message::Quit;
if let Message::Write(text) = msg {
println!("Write: {}", text);
} else {
println!("Not a write message");
}
}
```
### while let
```rust
fn main() {
let mut stack = vec![1, 2, 3];
while let Some(top) = stack.pop() {
println!("{}", top);
}
}
```
## Enums en Codigo Real
### Maquina de Estados
```rust
enum State {
Idle,
Loading,
Loaded(Vec),
Error(String),
}
fn main() {
let states = vec![
State::Idle,
State::Loading,
State::Loaded(vec!["item1".to_string()]),
State::Error("Network error".to_string()),
];
for state in states {
match state {
State::Idle => println!("Idle..."),
State::Loading => println!("Loading..."),
State::Loaded(items) => println!("Loaded {} items", items.len()),
State::Error(e) => println!("Error: {}", e),
}
}
}
```
## Resumen
- Los enums definen tipos con valores fijos
- Las variantes de enum pueden contener datos
- Option representa valores opcionales (Some/None)
- Result representa sucesso/fracaso (Ok/Err)
- match debe ser exhaustivo (cubrir todas las variantes)
- El operador ? propaga errores
- if let coincide con un patron unico
- while let itera mientras el patron coincide
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →