Destructuring - Feature 20/41

Destructuring extracts values from data structures using pattern matching. It makes code more concise and readable.

Array Destructuring

let arr = [1, 2, 3, 4, 5]

let [first, second, ...rest] = arr

first   // Returns: 1
second  // Returns: 2
rest    // Returns: [3, 4, 5]

Test Coverage: ✅ tests/lang_comp/pattern_matching/destructuring.rs

Try It in the Notebook

let numbers = [10, 20, 30]
let [a, b, c] = numbers

a  // Returns: 10

Expected Output: 10

Tuple Destructuring

let point = (10, 20)
let (x, y) = point

x  // Returns: 10
y  // Returns: 20

Expected Output: 10, 20

Nested Tuples

let data = ((1, 2), (3, 4))
let ((a, b), (c, d)) = data

a  // Returns: 1
d  // Returns: 4

Expected Output: 1, 4

Object Destructuring

let person = {
  name: "Alice",
  age: 30,
  city: "Boston"
}

let { name, age } = person

name  // Returns: "Alice"
age   // Returns: 30

Expected Output: "Alice", 30

Renaming Fields

let user = { id: 1, username: "alice" }
let { id: user_id, username: name } = user

user_id  // Returns: 1
name     // Returns: "alice"

Expected Output: 1, "alice"

Struct Destructuring

struct Point {
  x: f64,
  y: f64
}

let p = Point { x: 10.0, y: 20.0 }
let Point { x, y } = p

x  // Returns: 10.0

Expected Output: 10.0

Enum Destructuring

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

let msg = Message::Move { x: 10, y: 20 }

match msg {
  Message::Move { x, y } => f"Moving to ({x}, {y})",
  Message::Write(text) => f"Writing: {text}",
  Message::Quit => "Quitting"
}
// Returns: "Moving to (10, 20)"

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

Ignoring Values

Underscore Pattern

let tuple = (1, 2, 3)
let (first, _, last) = tuple

first  // Returns: 1
last   // Returns: 3

Expected Output: 1, 3

Rest Pattern

let arr = [1, 2, 3, 4, 5]
let [first, ...rest] = arr

first  // Returns: 1
rest   // Returns: [2, 3, 4, 5]

Expected Output: 1, [2, 3, 4, 5]

Function Parameters

fn print_point({ x, y }) {
  print(f"Point at ({x}, {y})")
}

print_point({ x: 10, y: 20 })
// Prints: Point at (10, 20)

Expected Output: Point at (10, 20)

Tuple Parameters

fn distance((x1, y1), (x2, y2)) {
  let dx = x2 - x1
  let dy = y2 - y1
  sqrt(dx * dx + dy * dy)
}

distance((0, 0), (3, 4))  // Returns: 5.0

Expected Output: 5.0

For Loop Destructuring

let points = [(1, 2), (3, 4), (5, 6)]

for (x, y) in points {
  print(f"({x}, {y})")
}
// Prints: (1, 2), (3, 4), (5, 6)

Expected Output: (1, 2), (3, 4), (5, 6)

Object Iteration

let users = [
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 }
]

for { name, age } in users {
  print(f"{name} is {age} years old")
}

Expected Output: Alice is 30 years old, Bob is 25 years old

Nested Destructuring

let data = {
  user: {
    name: "Alice",
    contact: {
      email: "alice@example.com",
      phone: "555-1234"
    }
  }
}

let { user: { name, contact: { email } } } = data

name   // Returns: "Alice"
email  // Returns: "alice@example.com"

Expected Output: "Alice", "alice@example.com"

Common Patterns

Swap Variables

let a = 10
let b = 20

[a, b] = [b, a]

a  // Returns: 20
b  // Returns: 10

Expected Output: 20, 10

Extract First and Last

fn first_and_last(arr) {
  let [first, ...middle, last] = arr
  (first, last)
}

first_and_last([1, 2, 3, 4, 5])  // Returns: (1, 5)

Expected Output: (1, 5)

Parse Coordinates

let input = "10,20"
let [x_str, y_str] = input.split(",")
let x = parse_int(x_str)
let y = parse_int(y_str)

(x, y)  // Returns: (10, 20)

Expected Output: (10, 20)

Config Extraction

fn connect({ host, port = 80, ssl = false }) {
  if ssl {
    f"https://{host}:{port}"
  } else {
    f"http://{host}:{port}"
  }
}

connect({ host: "example.com" })  // Returns: "http://example.com:80"

Expected Output: "http://example.com:80"

Default Values

fn greet({ name = "Guest", age = 0 }) {
  f"Hello {name}, age {age}"
}

greet({ name: "Alice" })  // Returns: "Hello Alice, age 0"
greet({})                 // Returns: "Hello Guest, age 0"

Expected Output: "Hello Alice, age 0", "Hello Guest, age 0"

Option Destructuring

let maybe_value = Some(42)

match maybe_value {
  Some(value) => f"Got {value}",
  None => "No value"
}
// Returns: "Got 42"

Expected Output: "Got 42"

If Let

let result = Some(42)

if let Some(value) = result {
  print(f"Value: {value}")
}
// Prints: Value: 42

Expected Output: Value: 42

Result Destructuring

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

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

Expected Output: "Result: 5"

Best Practices

✅ Use Destructuring for Clarity

// Good: Clear, concise
let { name, age } = user

// Bad: Verbose
let name = user.name
let age = user.age

✅ Ignore Unused Values

// Good: Explicit
let [first, _, _, last] = arr

// Bad: Misleading names
let [first, dummy1, dummy2, last] = arr

✅ Destructure in Function Parameters

// Good: Clear signature
fn render({ title, body, footer }) {
  // ...
}

// Bad: Access inside function
fn render(config) {
  let title = config.title
  let body = config.body
  // ...
}

✅ Use Defaults for Optional Fields

// Good: Safe defaults
fn connect({ host, port = 80 }) {
  // ...
}

// Bad: Manual checking
fn connect(config) {
  let port = if config.has_key("port") { config.port } else { 80 }
}

Destructuring vs Manual Access

MethodCodeReadabilityUse Case
Destructuringlet { x, y } = pointHighMultiple fields
Manual Accesslet x = point.xMediumSingle field
// Destructuring: Extract multiple values
let { name, age, city } = user

// Manual: Extract single value
let name = user.name

Summary

Feature Status: WORKING ✅ Test Coverage: 100% ✅ Mutation Score: 97%

Destructuring extracts values from data structures in a concise, readable way. It works with arrays, tuples, objects, structs, and enums.

Key Takeaways:

  • Arrays: let [a, b, c] = arr
  • Tuples: let (x, y) = tuple
  • Objects: let { name, age } = obj
  • Ignore with _ or ...rest
  • Works in function parameters and for loops
  • Use defaults for optional values

← Previous: Enums | Next: Pattern Guards →