16 releases (9 breaking)
0.10.0 | Feb 29, 2024 |
---|---|
0.9.0 | Nov 17, 2023 |
0.8.1 | Dec 6, 2022 |
0.8.0 | Jun 30, 2022 |
0.1.5 | Nov 25, 2019 |
#90 in Rust patterns
324,372 downloads per month
Used in 219 crates
(54 directly)
41KB
635 lines
Correct by Construction Non-Empty List
This package exposes a type NonEmpty<T>
with a data representation
that guarantees non-emptiness statically:
struct NonEmpty<T>(T, Vec<T>)
The library is meant to have an interface similar to std::vec::Vec
:
use nonempty::NonEmpty;
let mut l = NonEmpty::new(42);
assert_eq!(l.first(), &42);
l.push(36);
l.push(58);
let v: Vec<i32> = l.into();
assert_eq!(v, vec![42, 36, 58]);
lib.rs
:
A Non-empty growable vector.
Non-emptiness can be a powerful guarantee. If your main use of Vec
is as
an Iterator
, then you may not need to distinguish on emptiness. But there
are indeed times when the Vec
you receive as as function argument needs to
be non-empty or your function can't proceed. Similarly, there are times when
the Vec
you return to a calling user needs to promise it actually contains
something.
With NonEmpty
, you're freed from the boilerplate of constantly needing to
check is_empty()
or pattern matching before proceeding, or erroring if you
can't. So overall, code, type signatures, and logic become cleaner.
Consider that unlike Vec
, NonEmpty::first
and NonEmpty::last
don't
return in Option
, they always succeed.
Examples
The simplest way to construct a NonEmpty
is via the nonempty
macro:
use nonempty::{NonEmpty, nonempty};
let l: NonEmpty<u32> = nonempty![1, 2, 3];
assert_eq!(l.head, 1);
Unlike the familiar vec!
macro, nonempty!
requires at least one element:
use nonempty::nonempty;
let l = nonempty![1];
// Doesn't compile!
// let l = nonempty![];
Like Vec
, you can also construct a NonEmpty
the old fashioned way with
NonEmpty::new
or its constructor:
use nonempty::NonEmpty;
let mut l = NonEmpty { head: 42, tail: vec![36, 58] };
assert_eq!(l.head, 42);
l.push(9001);
assert_eq!(l.last(), &9001);
And if necessary, you're free to convert to and from Vec
:
use nonempty::{NonEmpty, nonempty};
let l: NonEmpty<u32> = nonempty![42, 36, 58, 9001];
let v: Vec<u32> = l.into();
assert_eq!(v, vec![42, 36, 58, 9001]);
let u: Option<NonEmpty<u32>> = NonEmpty::from_vec(v);
assert_eq!(Some(nonempty![42, 36, 58, 9001]), u);
Caveats
Since NonEmpty
must have a least one element, it is not possible to
implement the FromInterator
trait for it. We can't know, in general, if
any given Iterator
actually contains something.
Features
serialize
:serde
support.arbitrary
:arbitrary
support.
Dependencies
~190KB