Finding a list everyone agrees on isn't going to be easy. But I think we can choose the most commonly used things, that have a simple to use API, and that can be added to the std lib without too many difficulties. I have experience regarding what lazy methods are more commonly useful.
This is a first draft of a list. (the "=>" is my suggestion to rename the function for the std library).
The ones I suggest are: cartesian, chunks, combinations, combinations_n, copy_from, dedup, fill, fold1, group_by, Index, join, merge, multi_merge, multizip, permutations, show, sorted, sorted_by, sorted_by_key, step_by, to_vec.
See also:
Macros:
- iproduct => cartesian
- izip => multizip
Zipping and cartesian product are two common operations to do. Such things also show that there's some need for variadic generic functions in Rust...
Lazy iterator methods:
- step => step_by
step_by is a sufficiently common operation, and it's easy to use, having it only for numeric intervals is bad.
- format_default => show
It's very handy during debugging, etc.
But show() should take no arguments:
let s = (1 .. 5).map(|i| i * i);
println!("{:?}", s.show());
And print:
[1, 4, 9, 16]
Can we add a new formatting syntax to print/println? (Idea stolen from D language):
let s = (1 .. 5).map(|i| i * i);
println!("{:{:?; }}", s.show());
Could print:
{1; 4; 9; 16}
So just the .show() adaptor suffices.
- join
["a", "b", "c"].iter().join(", ")
It's a sufficiently common operation, and it's easy to use. Creating an intermediate vector is wasteful and noisy.
If and when Rust gets default arguments, we can add the join() with a default argument.
- fold1
Sufficiently common operation, and quite handy.
- collect_vec => to_vec
Common operation. Very easy to use. Quite handy. But I prefer a shorter name.
- set_from => copy_from
Sufficiently common operation, handy and easy to use.
An alternative alternative (inverted) API (from D language):
let mut xs = [0; 4];
(1 ..).copy_to(&mut xs.iter_mut());
assert_eq!(xs, [1, 2, 3, 4]);
- fill
I'd also like something to fill an array:
arr = 10; // D language code
Arrays.fill(arr, 10); // Java code
arr[2 .. $] = 10; // D code
In Rust you write something like this, that is longer and more bug-prone:
for i in 0 .. arr.len() { arr[i] = 10; }
for i in 2 .. arr.len() { arr[i] = 10; }
In Rust:
arr[0 ..].fill(10);
arr[2 ..].fill(10);
That's similar to:
std::iter::repeat(10).copy_to(&arr[0 ..]);
std::iter::repeat(10).copy_to(&arr[2 ..]);
- Index<Range> for all lazy iterables
It's a sufficiently common need (similar to islice of Python itertools), but instead of:
let it = iproduct!(0..3, 0..2, 0..2).slice(3 .. 5);
I'd like to write:
let it = iproduct!(0..3, 0..2, 0..2)[3 .. 5];
- dedup
This lazy operation is handy, sufficiently common, and easy to use and remember.
Currently in Itertools this is defined for all iterables, but I'd like it to be defined only for something that is statically known to be sorted. A sorted iterable comes from iterating the result of a sorting, or from a function that verifies (or assumes!) that an iterable is sorted.
- sorted
- sorted_by
- sorted_by_key
Easy to use and understand, handy, and allow to not break the chains of iterators.
- combinations
- combinations_n
- permutations
Handy in lot of situations. Able to shorten your code.
- merge
- kmerge => multi_merge
As dedup it should only be defined on iterables that are statically known to be sorted...
- group_by_lazy => group_by
- chunks_lazy => chunks
They are handy and commonly useful, they are present in D language and other languages. But I guess they aren't easy to add to the stdandard library.
Probably it's a good idea to add few more function, not currently present in itertools, but the ones listed here cover lot of the missing ground already.