Description
Current situation
Right now, many operation you can do with a string are hard coded to one specific type, like &str
or char
. For example:
let mut s = ~"";
s.push_str("foo");
s.push_char('a');
s.contains("foo");
s.contains_char('a');
Improving the API
Using traits and generics, these two examples could get boiled down into one contains
and one push
, which would accept either type while still being just as efficient as before.
There are quite a few methods that would benefit from such genericy, and so far I've identified two different kinds of traits:
-
StrPushable
- Anything that can be pushed to a string. String slices andchar
would implement this, but also things likeAscii
could.
Functions that would benefit from this include:push() replace() ...
This might be implementable with
fmt::Default
instead, but I'm not sure if it's a good idea to do that, as it would mean you could push anything to a string that implements that trait. -
StrMatcher
- Anything that could be used to find a string pattern in a string.
Again, string slices andchar
would implement it, as well as predicate functions like|char| -> bool
, theAscii
type, or things like a regex type.
A trait like this already exists in a limited form with theCharEq
trait, and would if properly extend be useful for a number of functions:split() // all variants replace() find() contains() ...
How it could look like
let mut s = ~"";
s.push("Hello");
s.push('!');
s.push(" aaa bbb ccc".as_ascii().to_upper());
assert_eq!(s, ~"Hello! AAA BBB CCC");
assert!(s.contains('!'));
assert!(s.contains(char::is_whitespace));
assert!(s.contains(regex("AA+")));
assert_eq!(s.split('!').collect(), ~["Hello", " AAA BBB CCC"]);
assert_eq!(s.split(char::is_whitespace).collect(), ~["Hello!", "AAA", "BBB", "CCC"]);
assert_eq!(s.split(regex("AA+")).collect(), ~["Hello! ", "A BBB CCC"]);
Status
I'm currently working on trying out this approach, to see if there are any rough edges or issues I haven't though of, but I think this would bring the string API a great step forward.