[][src]Module smart_access::iter_mut

Support for arbitrary mutating iterators. Requires iter_mut.

This module requires the alloc feature: our Cps values are affine traversals, thus they must have all the iteration results simultaneously, which in turn requires allocating memory at runtime.

This module depends on the multiref crate. The Slice type is re-exported from multiref. You can read the docs or simply use the At impls for Slice (they are the same as for normal slices).

An example

use smart_access::{ Cps, iter_mut::Bounds };
use std::collections::BTreeMap;

let mut map = BTreeMap::<i32, BTreeMap::<&'static str, i32>>::new();

map.at( (1, BTreeMap::new()) ).access(|inner| {
    inner.insert("a", 2);
    inner.insert("b", 3);
    inner.insert("c", 4);
});
 
map.at( (5, BTreeMap::new()) ).access(|inner| {
    inner.insert("a", 6);
    inner.insert("b", 7);
});
 
map.at( (8, BTreeMap::new()) ).access(|inner| {
    inner.insert("a", 9);
    inner.insert("x", 10);
});
 
// Hurrah!!! CPS without callback hell!
map.range_mut(5..).map(|(_,v)| v).at(Bounds(..)).at(1).at("a").replace(11);

assert!(map.at(&8).at("a").get_clone() == Some(11));

// And now enter batches (and another level of callbacks, 
// but still unlike a typical pyramidal callback hell):
map.range_mut(..=5).map(|(_,v)| v).at(Bounds(..)).batch_ct()
    .add(|x, _| x.at(0).at("c").replace(12))
    .add(|x, _| x.at(0).at("a").replace(13))
    .add(|x, _| x.at(1).at("b").replace(14))
    .run();

assert!(map.at(&1).at("c").get_clone() == Some(12));
assert!(map.at(&1).at("a").get_clone() == Some(13));
assert!(map.at(&5).at("b").get_clone() == Some(14));

Usage

Any Iterator (exactly Iterator, not IntoIterator) has At<Bounds<R>> implemented for every type R of usize-indexed ranges.

For example, to access the three elements of a BTreeMap with the smallest keys, you can write

map.iter_mut().map(|kv| kv.1).at(Bounds(..3)).access( |xs| { /* do something */ } );

But the main usecase is to allow indices denoting complex places. Suppose that you want to describe a place “every third element of an array”.

It can be done with the following code

struct EveryThird;

impl<T> At<EveryThird> for [T] {
    type View = Slice<T>;  // there must be Slice<T> instead of [T]

    fn access_at<R, F>(&mut self, _: EveryThird, f: F) -> Option<R> where
        F: FnOnce(&mut Slice<T>) -> R
    {
        self.chunks_mut(3)
            .map(|x| unsafe { x.get_unchecked_mut(0) })
            .access_at(Bounds(..), f)  // the key part
    }
}

// And now the following is possible:
let mut foo = vec![ vec![1, 2, 3, 4], vec![5, 6, 7] ];

foo.at(0).at(()).at(EveryThird).access(|slice| {
    for x in slice.as_mut() { **x = 8; }
});
assert!(foo == vec![vec![8, 2, 3, 8], vec![5, 6, 7]]);

Structs

Bounds

A newtype-wrapper around slice bounds.

Slice

A wrapper for a slice of references.