Currently Add
is implemented on Vec
only to append slices:
impl<'a, T: Clone> Add<&'a [T]> for Vec<T> {
type Result = Vec<T>;
fn add(self, rhs: &'a [T]) -> Vec<T> { ... }
}
This is really convenient when Vec
is used in folds as an accumulator. While sometimes map()
+collect::<Vec<_>>()
can be used instead of fold()
, it is not always the case, for example, when there is something else in the accumulator. The same thing also holds for String
.
However, this does require that the RHS must be a slice, which is not always possible. While you can write e.g.
let v = vec![1u, 2, 3];
v.iter().fold(Vec::new(), |a, &x| a + [x].as_slice())
it is really ugly. For strings, however, even this is not possible - you can’t turn a char
into a slice in general without allocation. You have to drop to push()
method which does not return the string back, so the closure must have two statements in it:
let s = "abcde".to_string();
s.chars().fold(String::new(), |mut a, c| { a.push(c); a });
If Vec<T>
and String
implemented Add<T>
/Add<char>
:
impl<T> Add<T> for Vec<T> {
type Result = Vec<T>;
fn add(self, rhs: T) -> Vec<T> {
self.push(rhs);
self
}
}
(similarly for String
), then the fold can be written just as
let s = "abcde".to_string();
s.chars().fold(String::new(), |a, c| a + c);
Other growable collections could probably be improved in a similar way.
What do you think?