5 unstable releases
| 0.10.1 | May 26, 2025 |
|---|---|
| 0.10.0 | May 18, 2025 |
| 0.9.1 | May 16, 2025 |
| 0.9.0 | May 14, 2025 |
| 0.1.0 | May 4, 2025 |
#414 in Data structures
276 downloads per month
69KB
900 lines
quantor
Declarative logic for iterators and collections.
quantor lets you express conditions like forall, exists, none, and existsforall directly over data — making filtering, validation, and testing expressive, readable, and idiomatic.
Why quantor?
Rust's iterator methods are powerful, but when you want to write logic that reads like:
- "All elements are even"
- "At least one user is active"
- "Exactly three items matched a condition"
you're often stuck with .all(), .any(), .filter().count(), and some assert! noise.
With quantor, your code becomes declarative and reflects the logic you care about, not the mechanics.
Highlights
- Quantifiers —
forall,exists,none,exactly_one,exactly_n,all_equal,pairwise,forallexists, and more. - Assertions — Runtime logic assertions like
assert_forall!,assert_unique!,assert_pairwise!, with expressive failure output. - Predicate-based selection — Filter, deduplicate, or extract based on logic:
select_where,select_unique,select_duplicates. - Diagnostics — Inspect failing indices, collect mismatches, or integrate with fuzzing tools using
QuantorError. - Rust-native, ergonomic API – Works with any
IntoIterator, zero dependencies, and optional.method()trait extension.
Example & Comparison
If you're validating product data from an online shop:
use quantor::{forall, existsforall, quantify, assert_unique};
#[derive(Debug)]
struct Product {
id: u32,
price: f64,
tags: Vec<&'static str>,
}
#[derive(Debug)]
struct Policy {
required_tag: &'static str,
}
let products = vec![
Product { id: 1, price: 19.99, tags: vec!["organic", "new"] },
Product { id: 2, price: 29.99, tags: vec!["new", "eco"] },
Product { id: 3, price: 49.99, tags: vec!["premium"] },
];
let policies = vec![
Policy { required_tag: "new" },
Policy { required_tag: "eco" },
];
// All quantify!-macro options reside as functions in the quantor crate.
// Each policy must be satisfied by at least one product.
quantify!(forallexists p in &policies, prod in &products =>
prod.tags.contains(&p.required_tag)
)?;
// At least one product is eco-friendly.
quantify!(exists p in &products => p.tags.contains(&"eco"))?;
// All products are priced.
forall(&products, |p| p.price > 0.0)?;
// IDs are unique.
assert_unique!(&products.iter().map(|p| p.id).collect::<Vec<_>>());
This is readable, declarative, and robust – and every check returns a Result with index-level error diagnostics, while the quantify! macro makes sure you can write conditions comfortably.
Installation
Add quantor to your Cargo.toml:
quantor = "0.10"
Optional features:
method-api— Enables.forall(),.exists(),.select_where(), etc. on slices and iterators.debug-tools— Enablesdebug_assert_*anddebug_*macros for non-panicking diagnostics.
📚 Documentation
See docs.rs for full API documentation and examples.
Changelog
See changelog.md for version history.
FAQ
Why does forall return Result<(), QuantorError> instead of bool?
Because failed logical checks are diagnostics, not just false. You get indexed errors and rich messages, not just silent failures.
What’s the difference between select_where and .filter()?
select_where is a semantic wrapper — it describes intent. It’s also easier to reuse and test.
Contributing & Feedback
If quantor made your validation or test code cleaner, I'd love to hear about it.
Have ideas? Open an issue or PR!