itertools is a Rust library that provides extra functionality for Rust’s iterators: extra adaptors, methods, free functions, and macros. We are now releasing version 0.5.0, which is a significant step up in consistency and clarity.

The release goals were:

We want to increase consistency, keep all the very useful stuff, remove the things that are never used, and move out the things that are better off in other crates.

The main user-noticable features are intended to be that the docs are easier to navigate, useful things now have shorter names, and there are lots of free functions in the crate’s root, previously hidden inside itertools::free.

One popular and really useful feature that got a shorter name is .format(), which allows you to format each element in an iterator:

use itertools::Itertools;

let data = [1.1, 2.71828, -3.];
println!("{:.2}", data.iter().format(", "));
// output is "1.10, 2.72, -3.00"

Other renames are .group_by_lazy().group_by() and .chunks_lazy().chunks(), and many others. The most used items, like these mentioned, have the old name remain with a deprecation warning (this is also the first release where the required Rust version is such that we can use deprecation warnings).

When it comes to free functions, this one is my favourite, it’s just the usual .enumerate() in a new form:

use itertools::enumerate;

let values = vec![0; 16];
for (i, elt) in enumerate(&mut values) {
    /* loop body */
}

What I see here is the power shift that occurred when IntoIterator was introduced. We chain iterator adaptors on Iterators, but iterations start out with IntoIterators a lot of the time. Free functions are often just as neat to use, since we can call them on iterables directly, without manual calls to .iter(), .iter_mut() and so on. Another up and coming free function is cloned(&collection)!

There were new features in 0.5 too! As a last minute thing, @malbarbo contributed a generalization of the pairs of combinations iterator that was previously called .combinations(); it is now .tuple_combinations() which handles 1 to 4-tuples of combinations:

use itertools::Itertools;

for (i, j, k) in (1..5).tuple_combinations() {
    // The loop goes through
    // (1, 2, 3) (1, 2, 4), (1, 3, 4), (2, 3, 4) and then it's done.
    // remember: in combinations the order of the elements does not matter,
    // in permutations it does.
}

Another new feature is Either. It is an enum with variants Left and Right. It’s very generic, but itertools reexports it for a couple of reasons: .partition_map() already needs generic selection of elements to either the left or right side; Either<L, R> implements Iterator itself when L and R are iterators and is thus its own kind of adapter; and lastly, we can use Either to express some more nice iterator adapters in the future (ideas).

I took care to bump crate either to version 1.0 before pushing it into the limelight like this, in case it proliferates we want its version story to be friction free from here on out.

The last job the 0.5 release had was to remove unstable, unused or ill fitting parts of the library. mend_slices is super cool but doesn’t have a real use case, so we pawn it off to crate odds along with slice-focused tools Stride and StrideMut. linspace needs numerical traits, so it lives in itertools-num now.

The full changelog is in the README. These were mostly just the breaking changes, we’ll continue to add a few features now that we have a nice clean base.