I have a function that needs to take in a list of keys (strings), which need to be iterated over multiple times.
This works:
fn decode_list<I, K>(it: I)
where
I: IntoIterator<Item = K> + Clone,
K: AsRef<str>
{
for idx in 0..2 {
for n in it.clone() {
let nm = n.as_ref();
}
}
}
fn main() {
decode_list(["Id", "Name", "Age"]);
}
But I'm curious if it's possible to eliminate the need for the Clone? There are a number of posts about this, using HRTB, on these forums, but my attempts at adapting them cause the call to decode_list() to no longer be accepted.
but you don't have to, iterators can be cheap to clone, although you do need to find the right iterator type. in your example, cloning an array is not cheap when the array is large, but cloning a reference or slice (or an explicit Iterator like std::slice::Iter) is very cheap, i.e.
fn main() {
// this will clone the array, which is bad for large array
decode_list(["Id", "Name", "Age"]);
// this will clone the array reference
decode_list(&["Id", "Name", "Age"]);
// this will clone the slice
decode_list(&["Id", "Name", "Age"][..]);
// this will clone the `std::slice::Iter`
decode_list(["Id", "Name", "Age"].iter());
}
My intuition was to use references and use HRTB to say a reference to I implements IntoIterator.
That seems to have worked, but I feel there's a gotcha somewhere:
fn decode_list<I, K>(it: I)
where
for<'i> &'i I: IntoIterator<Item = &'i K>,
for<'k> &'k K: AsRef<str>,
{
for idx in 0..2 {
for n in &it {
let nm = n.as_ref();
}
}
}