Comprehensive functional programming abstractions for Rust, providing Java-style functional interfaces adapted to Rust's ownership model.
This crate provides a complete set of functional programming abstractions inspired by Java's functional interfaces, carefully adapted to Rust's ownership system. It offers multiple implementations for each abstraction (Box/Arc/Rc) to cover various use cases from simple single-threaded scenarios to complex multi-threaded applications.
- Complete Functional Interface Suite: 24 core functional abstractions with multiple variants
- High-Performance Concurrency: Uses parking_lot Mutex for superior thread synchronization performance
- Multiple Ownership Models: Box-based single ownership, Arc-based thread-safe sharing, and Rc-based single-threaded sharing
- Flexible API Design: Trait-based unified interface with concrete implementations optimized for different scenarios
- Method Chaining: All types support fluent API and functional composition
- Thread-Safety Options: Choose between thread-safe (Arc) and efficient single-threaded (Rc) implementations
- Zero-Cost Abstractions: Efficient implementations with minimal runtime overhead
Add this to your Cargo.toml:
[dependencies]
qubit-function = "0.7.1"This crate provides 24 core functional abstractions, each with multiple implementations:
Tests whether a value satisfies a condition, returning bool.
Trait: Predicate<T>
Core Method: test(&self, value: &T) -> bool
Closure Equivalent: Fn(&T) -> bool
Implementations:
BoxPredicate<T>- Single ownership, non-cloneableArcPredicate<T>- Thread-safe, cloneableRcPredicate<T>- Single-threaded, cloneable
Example:
use qubit_function::{Predicate, ArcPredicate};
let is_even = ArcPredicate::new(|x: &i32| x % 2 == 0);
let is_positive = ArcPredicate::new(|x: &i32| *x > 0);
let combined = is_even.and(is_positive.clone());
assert!(combined.test(&4));
assert!(!combined.test(&-2));Tests whether two values satisfy a condition, returning bool.
Trait: BiPredicate<T, U>
Core Method: test(&self, first: &T, second: &U) -> bool
Closure Equivalent: Fn(&T, &U) -> bool
Implementations:
BoxBiPredicate<T, U>- Single ownershipArcBiPredicate<T, U>- Thread-safeRcBiPredicate<T, U>- Single-threaded
Example:
use qubit_function::{BiPredicate, BoxBiPredicate};
let sum_positive = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert!(sum_positive.test(&3, &4));
assert!(!sum_positive.test(&-5, &2));Accepts a value reference and performs side effects without returning a result.
Trait: Consumer<T>
Core Method: accept(&self, value: &T)
Closure Equivalent: Fn(&T)
Implementations:
BoxConsumer<T>- Single ownershipArcConsumer<T>- Thread-safeRcConsumer<T>- Single-threaded
Example:
use qubit_function::{Consumer, BoxConsumer};
let logger = BoxConsumer::new(|x: &i32| {
println!("Value: {}", x);
});
logger.accept(&42);Accepts a value reference and performs side effects once.
Trait: ConsumerOnce<T>
Core Method: accept(self, value: &T)
Closure Equivalent: FnOnce(&T)
Implementations:
BoxConsumerOnce<T>- Single ownership, one-time use
Accepts two value references and performs side effects without returning a result.
Trait: BiConsumer<T, U>
Core Method: accept(&self, first: &T, second: &U)
Closure Equivalent: Fn(&T, &U)
Implementations:
BoxBiConsumer<T, U>- Single ownershipArcBiConsumer<T, U>- Thread-safeRcBiConsumer<T, U>- Single-threaded
Example:
use qubit_function::{BiConsumer, BoxBiConsumer};
let sum_logger = BoxBiConsumer::new(|x: &i32, y: &i32| {
println!("Sum: {}", x + y);
});
sum_logger.accept(&10, &20);Accepts two value references and performs side effects once.
Trait: BiConsumerOnce<T, U>
Core Method: accept(self, first: &T, second: &U)
Closure Equivalent: FnOnce(&T, &U)
Implementations:
BoxBiConsumerOnce<T, U>- Single ownership, one-time use
Modifies the target value in place via &mut T with no return value. The mutator itself is stateless and is invoked with &self (equivalent to Fn(&mut T)).
Trait: Mutator<T>
Core Method: apply(&self, value: &mut T)
Closure Equivalent: Fn(&mut T)
Implementations:
BoxMutator<T>- Single ownershipArcMutator<T>- Thread-safeRcMutator<T>- Single-threaded
Example:
use qubit_function::{Mutator, BoxMutator};
let mut doubler = BoxMutator::new(|x: &mut i32| *x *= 2);
let mut value = 10;
doubler.apply(&mut value);
assert_eq!(value, 20);May be invoked once to mutate the target in place via &mut T (equivalent to FnOnce(&mut T)).
Trait: MutatorOnce<T>
Core Method: apply(self, value: &mut T)
Closure Equivalent: FnOnce(&mut T)
Implementations:
BoxMutatorOnce<T>- Single ownership, one-time use
Returns a value of type T on each get call with no input. The
supplier itself is stateless and uses &self (equivalent to
Fn() -> T).
Trait: Supplier<T>
Core Method: get(&self) -> T
Closure Equivalent: Fn() -> T
Implementations:
BoxSupplier<T>- Single ownership, lock-freeArcSupplier<T>- Thread-safe, lock-freeRcSupplier<T>- Single-threaded
Example:
use qubit_function::{Supplier, BoxSupplier};
let factory = BoxSupplier::new(|| String::from("Hello"));
assert_eq!(factory.get(), "Hello");May invoke get only once to return a single T (equivalent to
FnOnce() -> T).
Trait: SupplierOnce<T>
Core Method: get(self) -> T
Closure Equivalent: FnOnce() -> T
Implementations:
BoxSupplierOnce<T>- Single ownership, one-time use
Supplies a T using mutable internal state; successive get calls may differ (equivalent to FnMut() -> T).
Trait: StatefulSupplier<T>
Core Method: get(&mut self) -> T
Closure Equivalent: FnMut() -> T
Implementations:
BoxStatefulSupplier<T>- Single ownershipArcStatefulSupplier<T>- Thread-safe with parking_lot::MutexRcStatefulSupplier<T>- Single-threaded with RefCell
Example:
use qubit_function::{StatefulSupplier, BoxStatefulSupplier};
let mut counter = {
let mut count = 0;
BoxStatefulSupplier::new(move || {
count += 1;
count
})
};
assert_eq!(counter.get(), 1);
assert_eq!(counter.get(), 2);Computes a result from a borrowed input without consuming the input.
Trait: Function<T, R>
Core Method: apply(&self, input: &T) -> R
Closure Equivalent: Fn(&T) -> R
Implementations:
BoxFunction<T, R>- Single ownershipArcFunction<T, R>- Thread-safeRcFunction<T, R>- Single-threaded
Example:
use qubit_function::{Function, BoxFunction};
let to_string = BoxFunction::new(|x: &i32| format!("Value: {}", x));
assert_eq!(to_string.apply(&42), "Value: 42");Computes a result from a borrowed input once.
Trait: FunctionOnce<T, R>
Core Method: apply(self, input: &T) -> R
Closure Equivalent: FnOnce(&T) -> R
Implementations:
BoxFunctionOnce<T, R>- Single ownership, one-time use
Computes a result from a borrowed input while allowing mutable internal state.
Trait: StatefulFunction<T, R>
Core Method: apply(&mut self, input: &T) -> R
Closure Equivalent: FnMut(&T) -> R
Implementations:
BoxStatefulFunction<T, R>- Single ownershipArcStatefulFunction<T, R>- Thread-safe with parking_lot::MutexRcStatefulFunction<T, R>- Single-threaded with RefCell
Consumes an input value of type T and transforms it into a value of
type R.
Trait: Transformer<T, R>
Core Method: apply(&self, input: T) -> R
Closure Equivalent: Fn(T) -> R
Implementations:
BoxTransformer<T, R>- Single ownershipArcTransformer<T, R>- Thread-safeRcTransformer<T, R>- Single-threaded
Type Alias: UnaryOperator<T> = Transformer<T, T>
Example:
use qubit_function::{Transformer, BoxTransformer};
let parse = BoxTransformer::new(|s: String| s.parse::<i32>().unwrap_or(0));
assert_eq!(parse.apply("42".to_string()), 42);Consumes an input value once and transforms it into a value of type R.
Trait: TransformerOnce<T, R>
Core Method: apply(self, input: T) -> R
Closure Equivalent: FnOnce(T) -> R
Implementations:
BoxTransformerOnce<T, R>- Single ownership, one-time use
Type Alias: UnaryOperatorOnce<T> = TransformerOnce<T, T>
Consumes an input value and transforms it into a value of type R
while allowing mutable internal state.
Trait: StatefulTransformer<T, R>
Core Method: apply(&mut self, input: T) -> R
Closure Equivalent: FnMut(T) -> R
Implementations:
BoxStatefulTransformer<T, R>- Single ownershipArcStatefulTransformer<T, R>- Thread-safe with parking_lot::MutexRcStatefulTransformer<T, R>- Single-threaded with RefCell
Consumes two input values and transforms them into a result.
Trait: BiTransformer<T, U, R>
Core Method: apply(&self, first: T, second: U) -> R
Closure Equivalent: Fn(T, U) -> R
Implementations:
BoxBiTransformer<T, U, R>- Single ownershipArcBiTransformer<T, U, R>- Thread-safeRcBiTransformer<T, U, R>- Single-threaded
Type Alias: BinaryOperator<T> = BiTransformer<T, T, T>
Example:
use qubit_function::{BiTransformer, BoxBiTransformer};
let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
assert_eq!(add.apply(10, 20), 30);Consumes two input values and transforms them into a result while allowing mutable internal state.
Trait: StatefulBiTransformer<T, U, R>
Core Method: apply(&mut self, first: T, second: U) -> R
Closure Equivalent: FnMut(T, U) -> R
Implementations:
BoxStatefulBiTransformer<T, U, R>- Single ownershipArcStatefulBiTransformer<T, U, R>- Thread-safe with parking_lot::MutexRcStatefulBiTransformer<T, U, R>- Single-threaded with RefCell
Consumes two input values once and transforms them into a result.
Trait: BiTransformerOnce<T, U, R>
Core Method: apply(self, first: T, second: U) -> R
Closure Equivalent: FnOnce(T, U) -> R
Implementations:
BoxBiTransformerOnce<T, U, R>- Single ownership, one-time use
Type Alias: BinaryOperatorOnce<T> = BiTransformerOnce<T, T, T>
Accepts a value reference and performs side effects while allowing mutable internal state.
Trait: StatefulConsumer<T>
Core Method: accept(&mut self, value: &T)
Closure Equivalent: FnMut(&T)
Implementations:
BoxStatefulConsumer<T>- Single ownershipArcStatefulConsumer<T>- Thread-safe with parking_lot::MutexRcStatefulConsumer<T>- Single-threaded with RefCell
Accepts two value references and performs side effects while allowing mutable internal state.
Trait: StatefulBiConsumer<T, U>
Core Method: accept(&mut self, first: &T, second: &U)
Closure Equivalent: FnMut(&T, &U)
Implementations:
BoxStatefulBiConsumer<T, U>- Single ownershipArcStatefulBiConsumer<T, U>- Thread-safe with parking_lot::MutexRcStatefulBiConsumer<T, U>- Single-threaded with RefCell
Compares two values and returns an Ordering.
Trait: Comparator<T>
Core Method: compare(&self, a: &T, b: &T) -> Ordering
Closure Equivalent: Fn(&T, &T) -> Ordering
Implementations:
BoxComparator<T>- Single ownershipArcComparator<T>- Thread-safeRcComparator<T>- Single-threaded
Example:
use qubit_function::{Comparator, BoxComparator};
use std::cmp::Ordering;
let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
assert_eq!(cmp.compare(&5, &3), Ordering::Greater);Checks whether a condition or state holds without taking input.
Trait: Tester
Core Method: test(&self) -> bool
Closure Equivalent: Fn() -> bool
Implementations:
BoxTester- Single ownershipArcTester- Thread-safeRcTester- Single-threaded
Example:
use qubit_function::{Tester, BoxTester};
use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
let flag = Arc::new(AtomicBool::new(true));
let flag_clone = flag.clone();
let tester = BoxTester::new(move || flag_clone.load(Ordering::Relaxed));
assert!(tester.test());
flag.store(false, Ordering::Relaxed);
assert!(!tester.test());| Trait | Core Method Signature | Equivalent Closure Type |
|---|---|---|
Predicate<T> |
test(&self, value: &T) -> bool |
Fn(&T) -> bool |
BiPredicate<T, U> |
test(&self, first: &T, second: &U) -> bool |
Fn(&T, &U) -> bool |
Consumer<T> |
accept(&self, value: &T) |
Fn(&T) |
ConsumerOnce<T> |
accept(self, value: &T) |
FnOnce(&T) |
StatefulConsumer<T> |
accept(&mut self, value: &T) |
FnMut(&T) |
BiConsumer<T, U> |
accept(&self, first: &T, second: &U) |
Fn(&T, &U) |
BiConsumerOnce<T, U> |
accept(self, first: &T, second: &U) |
FnOnce(&T, &U) |
StatefulBiConsumer<T, U> |
accept(&mut self, first: &T, second: &U) |
FnMut(&T, &U) |
Mutator<T> |
apply(&self, value: &mut T) |
Fn(&mut T) |
MutatorOnce<T> |
apply(self, value: &mut T) |
FnOnce(&mut T) |
Supplier<T> |
get(&self) -> T |
Fn() -> T |
SupplierOnce<T> |
get(self) -> T |
FnOnce() -> T |
StatefulSupplier<T> |
get(&mut self) -> T |
FnMut() -> T |
Function<T, R> |
apply(&self, input: &T) -> R |
Fn(&T) -> R |
FunctionOnce<T, R> |
apply(self, input: &T) -> R |
FnOnce(&T) -> R |
StatefulFunction<T, R> |
apply(&mut self, input: &T) -> R |
FnMut(&T) -> R |
Transformer<T, R> |
apply(&self, input: T) -> R |
Fn(T) -> R |
TransformerOnce<T, R> |
apply(self, input: T) -> R |
FnOnce(T) -> R |
StatefulTransformer<T, R> |
apply(&mut self, input: T) -> R |
FnMut(T) -> R |
BiTransformer<T, U, R> |
apply(&self, first: T, second: U) -> R |
Fn(T, U) -> R |
StatefulBiTransformer<T, U, R> |
apply(&mut self, first: T, second: U) -> R |
FnMut(T, U) -> R |
BiTransformerOnce<T, U, R> |
apply(self, first: T, second: U) -> R |
FnOnce(T, U) -> R |
Comparator<T> |
compare(&self, a: &T, b: &T) -> Ordering |
Fn(&T, &T) -> Ordering |
Tester |
test(&self) -> bool |
Fn() -> bool |
Each trait has multiple implementations based on ownership model:
| Trait | Box (Single) | Arc (Thread-Safe) | Rc (Single-Thread) |
|---|---|---|---|
| Predicate | BoxPredicate | ArcPredicate | RcPredicate |
| BiPredicate | BoxBiPredicate | ArcBiPredicate | RcBiPredicate |
| Consumer | BoxConsumer | ArcConsumer | RcConsumer |
| ConsumerOnce | BoxConsumerOnce | - | - |
| StatefulConsumer | BoxStatefulConsumer | ArcStatefulConsumer | RcStatefulConsumer |
| BiConsumer | BoxBiConsumer | ArcBiConsumer | RcBiConsumer |
| BiConsumerOnce | BoxBiConsumerOnce | - | - |
| StatefulBiConsumer | BoxStatefulBiConsumer | ArcStatefulBiConsumer | RcStatefulBiConsumer |
| Mutator | BoxMutator | ArcMutator | RcMutator |
| MutatorOnce | BoxMutatorOnce | - | - |
| Supplier | BoxSupplier | ArcSupplier | RcSupplier |
| SupplierOnce | BoxSupplierOnce | - | - |
| StatefulSupplier | BoxStatefulSupplier | ArcStatefulSupplier | RcStatefulSupplier |
| Function | BoxFunction | ArcFunction | RcFunction |
| FunctionOnce | BoxFunctionOnce | - | - |
| StatefulFunction | BoxStatefulFunction | ArcStatefulFunction | RcStatefulFunction |
| Transformer | BoxTransformer | ArcTransformer | RcTransformer |
| TransformerOnce | BoxTransformerOnce | - | - |
| StatefulTransformer | BoxStatefulTransformer | ArcStatefulTransformer | RcStatefulTransformer |
| BiTransformer | BoxBiTransformer | ArcBiTransformer | RcBiTransformer |
| StatefulBiTransformer | BoxStatefulBiTransformer | ArcStatefulBiTransformer | RcStatefulBiTransformer |
| BiTransformerOnce | BoxBiTransformerOnce | - | - |
| Comparator | BoxComparator | ArcComparator | RcComparator |
| Tester | BoxTester | ArcTester | RcTester |
Legend:
- Box: Single ownership, cannot be cloned, consumes self
- Arc: Shared ownership, thread-safe, cloneable
- Rc: Shared ownership, single-threaded, cloneable
- -: Not applicable (Once types don't need sharing)
This crate adopts the Trait + Multiple Implementations pattern:
- Unified Interface: Each functional type has a trait defining core behavior
- Specialized Implementations: Multiple concrete types optimized for different scenarios
- Type Preservation: Composition methods return the same concrete type
- Ownership Flexibility: Choose between single ownership, thread-safe sharing, or single-threaded sharing
- High-Performance Concurrency: Uses parking_lot Mutex for superior synchronization performance
- Ergonomic API: Natural method chaining and functional composition
The examples/ directory contains comprehensive demonstrations for each type. Run examples with:
cargo run --example predicate_demo
cargo run --example consumer_demo
cargo run --example transformer_demoDetailed design documents are available in the doc/ directory for each major abstraction.
Licensed under Apache License, Version 2.0.
Haixing Hu starfish.hu@gmail.com