#value #infinity #ad-hoc-result

ad-hoc-result

A Rust library that extends the standard Result type with an AdHoc variant for returning fallback values alongside errors

1 unstable release

Uses new Rust 2024

new 0.1.0 Apr 26, 2025

#5 in #infinity

MIT license

15KB
64 lines

Ad Hoc Result

A Rust library providing an extension to Rust's standard Result type that allows for "ad hoc" values to be provided alongside errors.

This is useful in scenarios where a computation may fail but can still recommend a reasonable value to use despite the failure.

For example, this is needed when you can solve a linear system, but the accuracy is poor due to large condition numbers: you may want to return the computed solution as a recommendation, even though the operation is technically a failure.

Installation

Add this to your Cargo.toml:

[dependencies]
ad-hoc-result = "0.1.0"

Usage

The AdHocResult type extends the standard Result with a third variant:

enum AdHocResult<T, E> {
    Ok(T),          // Operation succeeded
    AdHoc(T, E),    // Operation failed, but here's a recommended value
    Err(E)          // Operation failed completely
}

Basic Example

use ad_hoc_result::AdHocResult;

// Function that returns AdHocResult
fn divide(a: f64, b: f64) -> AdHocResult<f64, String> {
    if b == 0.0 {
        // Operation failed, but we recommend using infinity
        AdHocResult::AdHoc(f64::INFINITY, "Division by zero".to_string())
    } else {
        AdHocResult::Ok(a / b)
    }
}

// Normal successful case
let result = divide(10.0, 2.0);
assert_eq!(result.unwrap(), 5.0);

// Ad-hoc case - failed but with a recommendation
let ad_hoc_result = divide(10.0, 0.0);
assert_eq!(ad_hoc_result.unwrap_adhoc(), f64::INFINITY);

Handling AdHocResult

The library provides several ways to handle the different variants:

use ad_hoc_result::AdHocResult;

let ok: AdHocResult<i32, &str> = AdHocResult::Ok(42);
let adhoc: AdHocResult<i32, &str> = AdHocResult::AdHoc(42, "Not ideal");
let err: AdHocResult<i32, &str> = AdHocResult::Err("Error");

// Extract only strictly successful values
assert_eq!(ok.unwrap(), 42);
// ok_value would panic on adhoc or err variants

// Extract success or recommended values
assert_eq!(ok.unwrap_adhoc(), 42);
assert_eq!(adhoc.unwrap_adhoc(), 42);
// adhoc_value would panic on err variant

// Convert to standard Result
assert_eq!(ok.to_result(), Ok(42));
assert_eq!(adhoc.to_result(), Err("Not ideal")); // Discards the recommended value
assert_eq!(err.to_result(), Err("Error"));

// Convert to Result treating AdHoc as success
assert_eq!(ok.to_result_with_adhoc(), Ok(42));
assert_eq!(adhoc.to_result_with_adhoc(), Ok(42)); // Uses the recommended value
assert_eq!(err.to_result_with_adhoc(), Err("Error"));

Creating AdHocResult

Use the new_* methods for cleaner creation:

let ok = AdHocResult::new_ok(42);
let adhoc = AdHocResult::new_adhoc(42, "Not ideal");
let err = AdHocResult::new_err("Error occurred");

Conversion To/From Result

Seamless conversion between Result and AdHocResult:

// From Result to AdHocResult
let ok_result: Result<i32, &str> = Ok(42);
let adhoc_ok: AdHocResult<i32, &str> = ok_result.into();

let err_result: Result<i32, &str> = Err("Error");
let adhoc_err: AdHocResult<i32, &str> = err_result.into();

// From AdHocResult to Result
let ok: AdHocResult<i32, &str> = AdHocResult::Ok(42);
let ok_result: Result<i32, &str> = ok.into(); // Result::Ok(42)

let adhoc: AdHocResult<i32, &str> = AdHocResult::AdHoc(42, "Not ideal");
let adhoc_result: Result<i32, &str> = adhoc.into(); // Result::Err("Not ideal")

License

This project is licensed under the GNU General Public License v3.0.

No runtime deps