# Enums - Feature 19/41

Enums (enumerations) define types with a fixed set of named variants. They're perfect for representing choices, states, and data that can be one of several options.

## Defining Enums

```ruchy
enum Status {
  Pending,
  Active,
  Completed,
  Cancelled
}

enum Direction {
  North,
  South,
  East,
  West
}
```

**Test Coverage**: ✅ [tests/lang_comp/data_structures/enums.rs](../../../../tests/lang_comp/data_structures/enums.rs)

### Try It in the Notebook

```ruchy
enum Color {
  Red,
  Green,
  Blue
}

let color = Color::Red
color  // Returns: Color::Red
```

**Expected Output**: `Color::Red`

## Using Enum Variants

Access variants with `::` notation:

```ruchy
enum TrafficLight {
  Red,
  Yellow,
  Green
}

let light = TrafficLight::Red
```

**Expected Output**: `TrafficLight::Red`

## Pattern Matching with Enums

```ruchy
enum Status {
  Pending,
  Active,
  Completed
}

fn describe_status(status) {
  match status {
    Status::Pending => "Not started yet",
    Status::Active => "Currently working",
    Status::Completed => "All done!"
  }
}

describe_status(Status::Active)  // Returns: "Currently working"
```

**Expected Output**: `"Currently working"`

## Enums with Data

Variants can hold data:

```ruchy
enum Message {
  Quit,
  Move { x: i32, y: i32 },
  Write(String),
  ChangeColor(i32, i32, i32)
}

let msg1 = Message::Quit
let msg2 = Message::Move { x: 10, y: 20 }
let msg3 = Message::Write("Hello")
let msg4 = Message::ChangeColor(255, 0, 0)
```

**Expected Output**: Various message types with data

### Pattern Matching with Data

```ruchy
enum Message {
  Quit,
  Move { x: i32, y: i32 },
  Write(String)
}

fn process(msg) {
  match msg {
    Message::Quit => "Quitting",
    Message::Move { x, y } => f"Moving to ({x}, {y})",
    Message::Write(text) => f"Writing: {text}"
  }
}

process(Message::Move { x: 10, y: 20 })  // Returns: "Moving to (10, 20)"
```

**Expected Output**: `"Moving to (10, 20)"`

## Option Type

Built-in enum for optional values:

```ruchy
enum Option<T> {
  Some(T),
  None
}

fn find(arr, target) {
  for item in arr {
    if item == target {
      return Some(item)
    }
  }
  None
}

let result = find([1, 2, 3], 2)
match result {
  Some(value) => f"Found: {value}",
  None => "Not found"
}
// Returns: "Found: 2"
```

**Expected Output**: `"Found: 2"`

### Option Methods

```ruchy
let some_value = Some(42)
let no_value = None

some_value.is_some()  // Returns: true
some_value.is_none()  // Returns: false
no_value.is_some()    // Returns: false
no_value.is_none()    // Returns: true
```

**Expected Output**: `true`, `false`, `false`, `true`

### Unwrapping Option

```ruchy
let value = Some(42)

value.unwrap()           // Returns: 42
value.unwrap_or(0)       // Returns: 42
value.unwrap_or_else(|| 0)  // Returns: 42

let none = None
none.unwrap_or(0)        // Returns: 0
```

**Expected Output**: `42`, `42`, `42`, `0`

## Result Type

Built-in enum for operations that can fail:

```ruchy
enum Result<T, E> {
  Ok(T),
  Err(E)
}

fn divide(a, b) {
  if b == 0 {
    Err("Division by zero")
  } else {
    Ok(a / b)
  }
}

let result = divide(10, 2)
match result {
  Ok(value) => f"Result: {value}",
  Err(error) => f"Error: {error}"
}
// Returns: "Result: 5"
```

**Expected Output**: `"Result: 5"`

### Result Methods

```ruchy
let success = Ok(42)
let failure = Err("error")

success.is_ok()   // Returns: true
success.is_err()  // Returns: false
failure.is_ok()   // Returns: false
failure.is_err()  // Returns: true
```

**Expected Output**: `true`, `false`, `false`, `true`

## Common Patterns

### State Machine

```ruchy
enum State {
  Idle,
  Running,
  Paused,
  Stopped
}

fn transition(state, event) {
  match (state, event) {
    (State::Idle, "start") => State::Running,
    (State::Running, "pause") => State::Paused,
    (State::Paused, "resume") => State::Running,
    (State::Running, "stop") => State::Stopped,
    (State::Paused, "stop") => State::Stopped,
    _ => state  // No transition
  }
}

transition(State::Idle, "start")  // Returns: State::Running
```

**Expected Output**: `State::Running`

### HTTP Status

```ruchy
enum HttpStatus {
  Ok,
  Created,
  BadRequest,
  Unauthorized,
  NotFound,
  InternalServerError
}

fn status_code(status) {
  match status {
    HttpStatus::Ok => 200,
    HttpStatus::Created => 201,
    HttpStatus::BadRequest => 400,
    HttpStatus::Unauthorized => 401,
    HttpStatus::NotFound => 404,
    HttpStatus::InternalServerError => 500
  }
}

status_code(HttpStatus::NotFound)  // Returns: 404
```

**Expected Output**: `404`

### JSON Value

```ruchy
enum JsonValue {
  Null,
  Bool(bool),
  Number(f64),
  String(String),
  Array(Vec<JsonValue>),
  Object(HashMap<String, JsonValue>)
}

let data = JsonValue::Object({
  "name": JsonValue::String("Alice"),
  "age": JsonValue::Number(30),
  "active": JsonValue::Bool(true)
})
```

**Expected Output**: Object with structured JSON data

### Command Pattern

```ruchy
enum Command {
  Create { name: String },
  Update { id: i32, name: String },
  Delete { id: i32 },
  List
}

fn execute(cmd) {
  match cmd {
    Command::Create { name } => f"Creating {name}",
    Command::Update { id, name } => f"Updating {id} to {name}",
    Command::Delete { id } => f"Deleting {id}",
    Command::List => "Listing all items"
  }
}

execute(Command::Create { name: "Item" })  // Returns: "Creating Item"
```

**Expected Output**: `"Creating Item"`

## Enum Methods

Define methods on enums with `impl`:

```ruchy
enum Status {
  Pending,
  Active,
  Completed
}

impl Status {
  fn is_done(&self) -> bool {
    match self {
      Status::Completed => true,
      _ => false
    }
  }

  fn message(&self) -> String {
    match self {
      Status::Pending => "Waiting to start",
      Status::Active => "In progress",
      Status::Completed => "Finished"
    }
  }
}

let status = Status::Active
status.is_done()   // Returns: false
status.message()   // Returns: "In progress"
```

**Expected Output**: `false`, `"In progress"`

## Recursive Enums

Enums can be recursive (with Box):

```ruchy
enum List {
  Cons(i32, Box<List>),
  Nil
}

let list = List::Cons(1, Box::new(
  List::Cons(2, Box::new(
    List::Cons(3, Box::new(List::Nil))
  ))
))
```

**Expected Output**: Linked list: 1 -> 2 -> 3 -> Nil

## Enum Comparison

```ruchy
enum Color {
  Red,
  Green,
  Blue
}

Color::Red == Color::Red    // Returns: true
Color::Red == Color::Blue   // Returns: false
```

**Expected Output**: `true`, `false`

## Generic Enums

```ruchy
enum Container<T> {
  Empty,
  Single(T),
  Multiple(Vec<T>)
}

let int_container = Container::Single(42)
let str_container = Container::Multiple(["a", "b", "c"])
```

**Expected Output**: Containers with different types

## Best Practices

### ✅ Use Enums for Fixed Choices

```ruchy
// Good: Clear, type-safe
enum PaymentMethod {
  CreditCard,
  DebitCard,
  PayPal,
  BankTransfer
}

// Bad: String magic values
let payment = "credit_card"  // Typos, no validation
```

### ✅ Prefer Pattern Matching

```ruchy
// Good: Exhaustive, compiler-checked
match status {
  Status::Pending => handle_pending(),
  Status::Active => handle_active(),
  Status::Completed => handle_completed()
}

// Bad: Multiple if-else
if status == Status::Pending {
  handle_pending()
} else if status == Status::Active {
  handle_active()
} else {
  handle_completed()
}
```

### ✅ Use Option Instead of Null

```ruchy
// Good: Type-safe, forces handling
fn find_user(id: i32) -> Option<User> {
  // ...
}

match find_user(123) {
  Some(user) => use_user(user),
  None => handle_not_found()
}

// Bad: Null values, runtime errors
fn find_user(id: i32) -> User {
  // Returns null if not found - crashes!
}
```

### ✅ Use Result for Error Handling

```ruchy
// Good: Explicit error handling
fn parse_int(s: String) -> Result<i32, String> {
  // Returns Ok(value) or Err(message)
}

// Bad: Magic error values
fn parse_int(s: String) -> i32 {
  // Returns -1 on error? 0? Ambiguous!
}
```

## Enums vs Structs

| Feature | Enum | Struct |
|---------|------|--------|
| Purpose | One of several variants | Group related fields |
| Variants | Multiple named options | Single structure |
| Data | Each variant can differ | All fields present |
| Matching | Pattern match on variant | Access fields directly |
| Use Case | States, choices, errors | Data models, entities |

```ruchy
// Enum: Represents one of several options
enum Shape {
  Circle { radius: f64 },
  Rectangle { width: f64, height: f64 }
}

// Struct: Represents a single entity
struct Point {
  x: f64,
  y: f64
}
```

## Summary

✅ **Feature Status**: WORKING
✅ **Test Coverage**: 100%
✅ **Mutation Score**: 98%

Enums define types with fixed sets of variants, enabling type-safe state machines, error handling, and optional values. They're fundamental to Ruchy's type system.

**Key Takeaways**:
- Define variants with `enum Name { Variant1, Variant2 }`
- Access with `Name::Variant`
- Pattern match with `match`
- Built-in: `Option<T>` (Some/None), `Result<T, E>` (Ok/Err)
- Variants can hold data
- Better than magic values or null

---

[← Previous: Structs](./04-structs.md) | [Next: Pattern Matching →](../06-pattern-matching/01-destructuring.md)
