#cmp

    This package provides utility functions for comparing values and the Reverse newtype wrapper for reversing comparison order.

    #Generic Comparison Functions

    The library provides generic comparison functions that work with any type implementing the Compare trait:

    ///|
    test "generic comparison" {
    // Works with numbers
    inspect(@cmp.maximum(3, 4), content="4")
    inspect(@cmp.minimum(3, 4), content="3")
    debug_inspect(@cmp.minmax(3, 4), content="(3, 4)")
    }

    #Reverse Comparison Order

    The @cmp.Reverse[T] newtype wrapper reverses the comparison order of any type implementing Compare. This is particularly useful for:

    • Creating min-heaps from max-heap data structures
    • Sorting in descending order
    • Reversing the priority in priority queues

    ///|
    test "reverse comparison" {
    let a = @cmp.Reverse(1)
    let b = @cmp.Reverse(2)

    // Normal comparison: 1 < 2, but reversed: 1 > 2
    inspect(a.compare(b), content="1")
    inspect(b.compare(a), content="-1")

    // Can be used with generic comparison functions
    @debug.debug_inspect(@cmp.maximum(a, b), content="Reverse(1)")
    @debug.debug_inspect(@cmp.minimum(a, b), content="Reverse(2)")
    }

    #Using Reverse with Collections

    @cmp.Reverse can be used with sorted collections to change their ordering:

    ///|
    test "reverse with arrays" {
    // Create an array with reversed integers for descending sort
    let arr : ReadOnlyArray[@cmp.Reverse[Int]] = [
    Reverse(3),
    Reverse(1),
    Reverse(4),
    Reverse(2),
    ]
    // When sorted, the array will be in descending order of the wrapped values
    @debug.debug_inspect(arr[0], content="Reverse(3)") // Access first element
    }

    #Comparison by Key

    With @cmp.maximum_by_key() and @cmp.minimum_by_key(), it is possible to compare values based on arbitrary keys derived from the them. This is particularly useful when you need to compare complex objects based on some specific aspect or field.

    ///|
    priv struct Person {
    name : String
    age : Int
    } derive(Debug)

    ///|
    test "cmp_by_key" {
    // Compare strings by their length
    let s1 = "hello"
    let s2 = "hi"
    let longer = @cmp.maximum_by_key(s1, s2, String::length)
    inspect(longer, content="hello")

    // Compare structs by a specific field
    let alice = { name: "Alice", age: 25 }
    let bob = { name: "Bob", age: 30 }
    let younger = @cmp.minimum_by_key(alice, bob, p => p.age)
    debug_inspect(
    younger,
    content=(
    #|{ name: "Alice", age: 25 }
    ),
    )

    // When keys are equal, the first argument is considered the minimum
    let p1 = ("first", 1)
    let p2 = ("second", 1)
    let snd = (p : (_, _)) => p.1
    @debug.assert_eq(@cmp.minimum_by_key(p1, p2, snd), p1)
    @debug.assert_eq(@cmp.maximum_by_key(p1, p2, snd), p2)
    }

    Reverse

    pub(all) struct Reverse[T](T) derive(Eq, Hash,
    Debug
    )

    A newtype wrapper that reverses the comparison order of the wrapped value.

    Reverse[T] is useful when you need to reverse the natural ordering of a type. For example, to create a min-heap from a max-heap data structure, or to sort in descending order instead of ascending order.

    Examples

    test {
    let a = @cmp.Reverse(1)
    let b = @cmp.Reverse(2)
    inspect(a.compare(b), content="1") // 1 > 2 in reversed order
    inspect(b.compare(a), content="-1") // 2 < 1 in reversed order
    inspect(a == a, content="true") // Equality works correctly
    @debug.debug_inspect(a, content="Reverse(1)") // Shows wrapped value
    }
    impl Compare for Reverse[T]
    impl Show for Reverse[T]

    Reverse::compare

    fn[T : Compare + Eq] Reverse::compare(a : Reverse[T], b : Reverse[T]) -> Int

    Reverse::equal

    fn[T : Eq] Reverse::equal(Reverse[T], Reverse[T]) -> Bool

    Reverse::hash

    fn[T : Hash] Reverse::hash(self : Reverse[T]) -> Int

    maximum

    fn[T : Compare + Eq] maximum(x : T, y : T) -> T

    Compares and returns the maximum of two values.

    Returns the second argument if the comparison determines them to be equal.

    Examples

    test {
    inspect(@cmp.maximum(1, 2), content="2")
    inspect(@cmp.maximum(2, 1), content="2")
    let fst = []
    let snd = []
    @cmp.maximum(fst, snd).push(0)
    debug_inspect(snd, content="[0]")
    }

    maximum_by_key

    fn[T, K : Compare + Eq] maximum_by_key(x : T, y : T, f : (T) -> K) -> T

    Returns the element that gives the maximum value from the specified function.

    Returns the second argument if the comparison determines them to be equal.

    Examples

    test {
    inspect(@cmp.maximum_by_key(1, -2, Int::abs), content="-2")
    inspect(@cmp.maximum_by_key(-2, 1, Int::abs), content="-2")
    inspect(@cmp.maximum_by_key(-2, 2, Int::abs), content="2")
    }

    minimum

    fn[T : Compare + Eq] minimum(x : T, y : T) -> T

    Compares and returns the minimum of two values.

    Returns the first argument if the comparison determines them to be equal.

    Examples

    test {
    inspect(@cmp.minimum(1, 2), content="1")
    inspect(@cmp.minimum(2, 1), content="1")
    let fst = []
    let snd = []
    @cmp.minimum(fst, snd).push(0)
    debug_inspect(fst, content="[0]")
    }

    minimum_by_key

    fn[T, K : Compare + Eq] minimum_by_key(x : T, y : T, f : (T) -> K) -> T

    Returns the element that gives the minimum value from the specified function.

    Returns the first argument if the comparison determines them to be equal.

    Examples

    test {
    inspect(@cmp.minimum_by_key(1, -2, Int::abs), content="1")
    inspect(@cmp.minimum_by_key(-2, 1, Int::abs), content="1")
    inspect(@cmp.minimum_by_key(-2, 2, Int::abs), content="-2")
    }

    minmax

    fn[T : Compare + Eq] minmax(x : T, y : T) -> (T, T)

    Returns both the minimum and maximum of two values as a tuple.

    Parameters:

    • x : The first value to compare.
    • y : The second value to compare.

    Returns a tuple (min, max) where the first element is the smaller value and the second element is the larger value. If the values are equal, returns (x, y).

    Examples:

    test {
    debug_inspect(@cmp.minmax(1, 2), content="(1, 2)")
    debug_inspect(@cmp.minmax(2, 1), content="(1, 2)")
    }

    minmax_by_key

    fn[T, K : Compare + Eq] minmax_by_key(x : T, y : T, f : (T) -> K) -> (T, T)

    Returns the minimum and maximum of two values based on a comparison function.

    Parameters:

    • x : The first value to compare.
    • y : The second value to compare.
    • f : A function that extracts a comparable key from each value.

    Returns a tuple (min, max) where the first element is the value that produces the smaller key and the second element is the value that produces the larger key. If the keys are equal, returns (x, y).

    Examples:

    test {
    debug_inspect(@cmp.minmax_by_key(1, -2, Int::abs), content="(1, -2)")
    debug_inspect(@cmp.minmax_by_key(-2, 1, Int::abs), content="(1, -2)")
    debug_inspect(@cmp.minmax_by_key(-2, 2, Int::abs), content="(-2, 2)")
    }

    Source Files