Hone logo
Hone
Problems

Implement expect for Option and Result in Rust

In Rust, unwrapping Option and Result types often involves using unwrap(), which can panic with a generic error message if the value is None or Err. This makes debugging difficult. The expect() method provides a more helpful alternative by allowing you to specify a custom panic message, which is invaluable for understanding the cause of a failure during development. This challenge will guide you through implementing this essential functionality yourself.

Problem Description

Your task is to create two macros, option_expect and result_expect, that mimic the behavior of Option::expect and Result::expect respectively. These macros should take two arguments: the value to unwrap (an Option or Result) and a string literal representing the panic message.

Key Requirements:

  • option_expect Macro:
    • Takes an Option<T> and a &'static str (the panic message).
    • If the Option is Some(v), it should return the inner value v.
    • If the Option is None, it should panic with the provided message.
  • result_expect Macro:
    • Takes a Result<T, E> and a &'static str (the panic message).
    • If the Result is Ok(v), it should return the inner value v.
    • If the Result is Err(e), it should panic with the provided message.

Expected Behavior:

When the Option is Some or the Result is Ok, the macro should behave like unwrap(). When the Option is None or the Result is Err, the macro should panic with the specific message provided.

Edge Cases:

  • Consider the types of the inner values in Option and Result. The macros should be generic enough to handle any type.
  • The panic message must be a string literal (&'static str).

Examples

Example 1: option_expect with Some

let value: Option<i32> = Some(42);
let unwrapped = option_expect!(value, "Expected a number, but got None");
// unwrapped will be 42

Explanation: The Option contains Some(42). option_expect extracts the inner value 42.

Example 2: option_expect with None (Panic)

let value: Option<i32> = None;
let unwrapped = option_expect!(value, "Expected a number, but got None");
// This line will panic with the message: "Expected a number, but got None"

Explanation: The Option is None. option_expect triggers a panic with the provided message.

Example 3: result_expect with Ok

let res: Result<String, std::io::Error> = Ok(String::from("Hello"));
let unwrapped = result_expect!(res, "Expected a string, but got an IO error");
// unwrapped will be String::from("Hello")

Explanation: The Result is Ok("Hello"). result_expect returns the inner string.

Example 4: result_expect with Err (Panic)

use std::io::{self, ErrorKind};

let res: Result<String, io::Error> = Err(io::Error::new(ErrorKind::NotFound, "File not found"));
let unwrapped = result_expect!(res, "Failed to read file");
// This line will panic with the message: "Failed to read file: File not found"
// (The specific error message from io::Error might also be appended by the default panic handler)

Explanation: The Result is Err. result_expect triggers a panic with the provided message.

Constraints

  • The macros must be implemented using Rust's macro_rules! syntax.
  • The panic message must be a string literal (&'static str).
  • The macros should be as generic as possible, working with any T in Option<T> and any T, E in Result<T, E>.
  • The macros should return the unwrapped value directly, not a reference unless the original Option/Result contained a reference.

Notes

  • Remember that macro_rules! allows you to define patterns and transformations.
  • You'll need to use the panic! macro internally.
  • Consider how to handle the different variants of Option and Result within your macro rules.
  • The goal is to replicate the core functionality and error-handling behavior of the standard library's expect methods.
Loading editor...
rust