pub struct SharedList<T: Clone>(_);
Expand description

A persistent, thread safe, list.

This list is suitable for a multi threaded environment. If do not need an immutable list that can be shared across threads (i.e., is Send + Sync, see List).

It’s implemented as an unrolled linked list, which is a single linked list which stores a variable amount of elements in each node. The capacity of any individual node for now is set to to be 256 elements, which means that until more than 256 elements are cons’d onto a list, it will remain a vector under the hood.

The list is also designed to leverage in place mutations whenever possible - if the number of references pointing to either a cell containing a vector or the shared vector is one, then that mutation is done in place. Otherwise, it is copy-on-write, maintaining our persistent invariant.

Performance Notes

The algorithmic complexity of an unrolled linked list matches that of a normal linked list - however in practice we have a decrease by the factor of the capacity of a node that gives us practical performance wins. For a list that is fully filled, iteration becomes O(n / 256), rather than the typical O(n). In addition, the unrolled linked list is able to avoid the costly cache misses that a typical linked list suffers from, seeing very realistic performance gains.

Let n be the number of elements in the list, and m is the capacity of a node. In the worst case, a node will be on average half filled. In the best case, all nodes are completely full. This means for operations that for a normal linked list may take linear time Θ(n), we get a constant factor decrease of either a factor of m or m / 2.

Implementations

Construct an empty list.

Get the number of strong references pointing to this list

Time: O(1)

Compare this list to another for pointer equality

Get the length of the list

Examples
let list = shared_list![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
assert_eq!(list.len(), 10);

Reverses the input list and returns a new list

Examples
let list = shared_list![1, 2, 3, 4, 5].reverse();
assert_eq!(list, shared_list![5, 4, 3, 2, 1])

Get the last element of the list. Returns None if the list is empty.

Examples
let list = shared_list![1, 2, 3, 4, 5];
assert_eq!(list.last().cloned(), Some(5));

Get the first element of the list. Returns None if the list is empty.

Examples
let list = shared_list![1, 2, 3, 4, 5];
let car = list.car();
assert_eq!(car, Some(1));

let list: SharedList<usize> = shared_list![];
let car = list.car();
assert!(car.is_none());

Returns a reference to the first element of the list. Returns None if the list is empty.

Examples
let list = shared_list![1, 2, 3, 4, 5];
let first = list.first().cloned();
assert_eq!(first, Some(1));

let list: SharedList<usize> = shared_list![];
let first = list.first();
assert!(first.is_none());

Get the “rest” of the elements as a list, excluding the first element

Examples
let list = shared_list![1, 2, 3, 4, 5];
let cdr = list.cdr().unwrap();
assert_eq!(cdr, shared_list![2, 3, 4, 5]);

let list = shared_list![5];
let cdr = list.cdr();
assert!(cdr.is_none());

Get the “rest” of the elements as a list. Alias for cdr

Gets the cdr of the list, mutably. Returns None if the next is empty - otherwise updates self to be the rest

Examples
let mut list = shared_list![1, 2, 3, 4, 5];
list.cdr_mut().expect("This list has a tail");
assert_eq!(list, shared_list![2, 3, 4, 5]);


let mut list = shared_list![1, 2, 3];
assert!(list.cdr_mut().is_some());
assert_eq!(list, shared_list![2, 3]);
assert!(list.cdr_mut().is_some());
assert_eq!(list, shared_list![3]);
assert!(list.cdr_mut().is_none());
assert_eq!(list, shared_list![]);

Gets the rest of the list, mutably. Alias for cdr_mut

Pushes an element onto the front of the list, returning a new list

Examples
let list = SharedList::cons(1, SharedList::cons(2, SharedList::cons(3, SharedList::cons(4, SharedList::new()))));
assert_eq!(list, shared_list![1, 2, 3, 4]);

Mutably pushes an element onto the front of the list, in place

Examples
let mut list = shared_list![];
list.cons_mut(3);
list.cons_mut(2);
list.cons_mut(1);
list.cons_mut(0);
assert_eq!(list, shared_list![0, 1, 2, 3])

Alias for cons_mut

Examples
let mut list = shared_list![];
list.push_front(3);
list.push_front(2);
list.push_front(1);
list.push_front(0);
assert_eq!(list, shared_list![0, 1, 2, 3])

Mutably pop the first value off of the list

Examples
let mut list = shared_list![1, 2, 3];
assert_eq!(list.pop_front().unwrap(), 1);
assert_eq!(list.pop_front().unwrap(), 2);
assert_eq!(list.pop_front().unwrap(), 3);
assert!(list.pop_front().is_none())

Push one value to the back of the list

Time: O(n)

Examples
let mut list = shared_list![];
list.push_back(0);
list.push_back(1);
list.push_back(2);
list.push_back(3);
assert_eq!(list, shared_list![0, 1, 2, 3])

Construct a new list from the first count elements from the current list

Examples
let list = shared_list![0, 1, 2, 3, 4, 5];
let new_list = list.take(3);
assert_eq!(new_list, shared_list![0, 1, 2]);

Returns the list after the first len elements of lst. If the list has fewer then len elements, then this returns None.

Examples
let list = shared_list![0, 1, 2, 3, 4, 5];
let new_list = list.tail(2);
assert_eq!(new_list.unwrap(), shared_list![2, 3, 4, 5]);

let no_list = list.tail(100);
assert!(no_list.is_none())

Constructs an iterator over the list

Get a reference to the value at index index in a list. Returns None if the index is out of bounds.

Append the list other to the end of the current list. Returns a new list.

Examples
let left = shared_list![1usize, 2, 3];
let right = shared_list![4usize, 5, 6];
assert_eq!(left.append(right), shared_list![1, 2, 3, 4, 5, 6])

Append the list ‘other’ to the end of the current list in place.

Examples
let mut left = shared_list![1usize, 2, 3];
let right = shared_list![4usize, 5, 6];
left.append_mut(right);
assert_eq!(left, shared_list![1, 2, 3, 4, 5, 6])

Checks whether a list is empty

Examples
let mut list = SharedList::new();
assert!(list.is_empty());
list.cons_mut("applesauce");
assert!(!list.is_empty());

Sorts the list

Examples
let mut list = shared_list![4, 2, 6, 3, 1, 5];
list.sort();
assert_eq!(list, shared_list![1, 2, 3, 4, 5, 6]);

Sorts the list according to the ordering

Examples
let mut list = shared_list![4, 2, 6, 3, 1, 5];
list.sort_by(Ord::cmp);
assert_eq!(list, shared_list![1, 2, 3, 4, 5, 6]);

Trait Implementations

Concatenate two lists

The resulting type after applying the + operator.

Concatenate two lists

The resulting type after applying the + operator.

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Returns the “default value” for a type. Read more

Extends a collection with the contents of an iterator. Read more

🔬 This is a nightly-only experimental API. (extend_one)

Extends a collection with exactly one element.

🔬 This is a nightly-only experimental API. (extend_one)

Reserves capacity in a collection for the given number of additional elements. Read more

Converts to this type from the input type.

Converts to this type from the input type.

Creates a value from an iterator. Read more

Creates a value from an iterator. Read more

Creates a value from an iterator. Read more

Feeds this value into the given Hasher. Read more

Feeds a slice of this type into the given Hasher. Read more

Get a reference to the value at index index in the vector.

Time: O(log n)

The returned type after indexing.

The type of the elements being iterated over.

Which kind of iterator are we turning this into?

Creates an iterator from a value. Read more

The type of the elements being iterated over.

Which kind of iterator are we turning this into?

Creates an iterator from a value. Read more

This method returns an Ordering between self and other. Read more

Compares and returns the maximum of two values. Read more

Compares and returns the minimum of two values. Read more

Restrict a value to a certain interval. Read more

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method returns an ordering between self and other values if one exists. Read more

This method tests less than (for self and other) and is used by the < operator. Read more

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more

This method tests greater than (for self and other) and is used by the > operator. Read more

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more

Method which takes an iterator and generates Self from the elements by “summing up” the items. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

Uses borrowed data to replace owned data, usually by cloning. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.