case_clause 0.1.3

case clause macro for rust
Documentation
#![warn(missing_docs)]
//! # Case Clause Macro
//! The purpose of the macro implemented here is to create an alternative to huge if else cascades.
//! ## Current State: The Idea is based on haskell [case clauses](https://www.haskell.org/tutorial/patterns.html):
//!
//! ```haskell
//! sign x |  x >  0 =  1
//!        |  x == 0 =  0
//!        |  x <  0 = -1
//! ```
//! This would normally look like this in [Rust](https://www.rust-lang.org/):
//! ```rust
//! # let x = 5; // Added variable declaration
//! let result = if x > 0 {
//!     1
//! } else if x == 0 {
//!     0
//! } else if x < 0 {
//!     -1
//! } else {
//!     0
//! };
//! ```
//! If you now want to display this using a match case, which is normally the environment in rust for pattern matching, it would look different:
//! ```rust
//! # let x = 5; //Added variable declaration
//! match x {
//!     x if x > 0 => 1,
//!     x if x == 0 => 0,
//!     x if x < 0 => -1,
//!     _ => 0,
//! };
//! ```
//! I found both solutions extremely clunky and therefore tiring to work with. That's why the macro from this crate works like this:
//! ```rust
//! use case_clause::case;
//! # let x = 5; // Added variable declaration
//! let result = case!(
//!     x > 0 => 1,
//!     x == 0 => 0,
//!     x < 0  => -1,
//!     true => 0,
//! );
//! ```
//! To be fair, this is a first step towards creating a more elegant alternative to rust's `match` environment, which still works elegantly when processing boolean values.

/// # A macro that provides Haskell-style case expressions for Rust.
///
/// This macro allows you to write guard-based pattern matching similar to Haskell's case expressions.
/// Each guard is evaluated in order, and the first one that evaluates to `true` will have its
/// corresponding result expression returned.
///
/// ## Examples
///
/// ```rust
/// use case_clause::case;
///
/// let x = 5;
/// let result = case!(
///     x > 10 => "large",
///     x > 0 => "positive",
///     x == 0 => "zero",
///     true => "negative"
/// );
/// assert_eq!(result, "positive");
/// ```
///
/// ## Panics
///
/// This macro will panic with "unreachable" if none of the guards match. Make sure to include
/// a catch-all case (like `true => default_value`) to avoid this.
#[macro_export]
macro_rules! case {
    ($($guard:expr => $result:expr),+ $(,)?) => {
        {
            #[allow(unreachable_patterns)]
            match () {
                $( _ if $guard => $result, )+
                _ => unreachable!("All cases should be covered by the guards"),
            }
        }
    };
}

/// # An alternative case macro that uses if-else chains instead of match expressions.
///
/// This macro provides similar functionality to `case!` but uses a chain of if-else
/// statements internally. Each condition is evaluated in order until one matches.
///
/// ## Examples
///
/// ```rust
/// use case_clause::case_pattern;
///
/// let x = -3;
/// let result = case_pattern!(
///     x > 0 => 1,
///     x == 0 => 0,
///     x < 0 => -1,
/// );
/// assert_eq!(result, -1);
/// ```
///
/// ## Panics
///
/// This macro will panic with "unreachable" if none of the conditions match. Make sure
/// to include a condition that will always be true as the last case.
#[macro_export]
macro_rules! case_pattern {
    ($($cond:expr => $result:expr),* $(,)?) => {
        $(if $cond { $result } else)*
        { unreachable!("No pattern matched") }
    };
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn it_works() {
        let x = 5;
        assert_eq!(
            case_pattern!(
                x > 0 => 1,
                x == 0 => 0,
                x < 0 => -1,
            ),
            1
        )
    }
    #[test]
    fn case_test() {
        let x = -3;
        assert_eq!(
            case!(
                        x > 0 => 1,
                        x == 0 => 0,
                        x < 0 => -1,
                    true => 0,
            ),
            -1
        )
    }
}