I have this generic function:
pub fn chain<'a, Head, Tail, HeadItem, TailItem>(
head: Head, tail: Tail
) -> impl Iterator<Item = &'a str> + 'a
where
Head: IntoIterator<Item = &'a TailItem> + 'a,
Tail: IntoIterator<Item = &'a HeadItem> + 'a,
HeadItem: AsRef<str> + ?Sized + 'a,
TailItem: AsRef<str> + ?Sized + 'a,
{
head.into_iter().map(|v| v.as_ref()).chain(tail.into_iter().map(|v| v.as_ref()))
}
It allows me to do the following:
fn f() {
let a: Vec<String> = vec!["1".to_string(), "2".into()];
let b: Vec<&str> = dbg!(chain(&a, ["A", "B"]).collect()); // 1, 2, A B
let c: Vec<String> = b.iter().map(|s| s.to_string()).collect();
dbg!(chain(&["A", "B"], &a).collect::<Vec<&str>>()); // A, B, 1, 2
dbg!(chain(&c, &a).collect::<Vec<&str>>()); // 1, 2, A, B, 1, 2
}
As an exercise, I'd like to turn this function into a trait that will allow me to do things like ["a", "b"].chain(&vec)
:
pub trait Chain<Tail, /* possibly more generics */>
/* where clauses */
{
type Output;
fn chain(&self, tail: Tail) -> Self::Output;
}
// TODO: impl Chain for &[&str], &[String], &Vec<&str>, &Vec<String> etc. to allow these:
fn g() {
let a: Vec<String> = vec!["1".to_string(), "2".into()];
dbg!(a.chain(["A", "B"]).collect::<Vec<&str>>()); // 1, 2, A, B
dbg!(a.chain(&a).collect::<Vec<&str>>()); // 1, 2, 1, 2
dbg!(["A", "B"].chain(&a).collect::<Vec<&str>>()); // A, B, 1, 2
dbg!(["A", "B"].chain(["1", "2"]).collect::<Vec<_>>()); // A, B, 1, 2
}
This is my attemp. But I am having difficulty to figure out the Self::Output
type in the impl because of the .map()
calls.
Appreciate your help and thanks in advance.