eclectic 0.9.0

Experimental collection traits.

Collection traits for generic programming.

This crate distinguishes three modes of access to a collection, as determined by marker bounds on the methods of each collection trait:

Marker Bound Enables Analogous To
(none) Read-only access to items and state &[T]
Mut Write access to items &mut [T]
Own Insertion and removal of items &mut Vec<T>

These bounds can be combined with each of the collection traits to enable different operations on the collection. For example, List on its own provides len and get, while List + Mut additionally provides get_mut and swap, and List + Own additionally provides clear and push.

Generic code should specify only those bounds that are needed for its operation, but may specify additional bounds for future compatibility. Generic code should also use the collection traits with a ?Sized bound in order to support slices and trait objects whenever possible.


Insertion sort:

use eclectic::{List, Mut};

fn insertion_sort<L: ?Sized + List + Mut>(list: &mut L) where L::Item: Ord {
    for i in 1..list.len() { // `len` is defined on `Collection`, a supertrait of `List`
        let mut j = i;

        while j > 0 && list.get(j) < list.get(j - 1) {
            list.swap(j, j - 1); // the `Mut` bound on `L` enables the use of `List::swap`
            j -= 1;

use std::collections::VecDeque;

let mut slice = ["c", "b", "a"];
insertion_sort(&mut slice as &mut [_]);
assert_eq!(slice, ["a", "b", "c"]);

let mut vec = vec!['c', 'b', 'a'];
insertion_sort(&mut vec);
assert_eq!(vec, ['a', 'b', 'c']);

let mut vec_deque: VecDeque<_> = vec![3, 2, 1].into_iter().collect();
insertion_sort(&mut vec_deque);
assert!(vec_deque.iter().eq(&[1, 2, 3]));

A Note on Trait Objects

A number of trait methods in this crate return a Box<Iterator>, which requires unnecessary heap allocation and opaqueness (e.g. erasure of traits like Clone and DoubleEndedIterator). This is to make up for the (hopefully temporary) inability to define higher-kinded associated types like:

trait Collection {
    type Drain<'a>: 'a + Iterator<Item = Self::Item>;

    fn drain<'a>(&'a mut self) -> Self::Drain<'a> where Self: Own;

If Rust acquires such types, the iterator- and entry-returning methods will be changed to use them.