str and String support indexing by various kinds of Range to produce a slice, but do not support indexing with a single index to produce a char. That would simplify such operations by not requiring duplication of the index expression or introduction of an iterator and unwrapping.
We can't actually do that because the Index trait can only return references. At best, we could return a string slice that contained exactly one character.
It can return a &char, though. And since char implements Copy and Clone, the caller can easily get a char from that if they want one.
But where would you _store_ the char?
That is,
impl Index<usize> for str {
type Output = char;
fn index(&self, index: usize) -> &char {
let c = self[index..].chars().next().unwrap()
return &c; // c doesn't live long enough.
}
}
Ah, I see. Unfortunate typing there. Ideally the '&' would have been included in the associated type Output, rather than implied inherently by Index. But in the absence of that, yes, that doesn't work.
The & can unfortunately not appear in the associated type only, because we can't bind it to the lifetime of &self in that case.
Foiled again by HKT!
They could implement Index<usize, Output=u8>. On the other hand, the forced choice of s.bytes() vs s.chars() raises awareness that they aren't the same.
Even without the problem of Index returning a reference, how do you image it would be implemented, if it returned a char? Strings in Rust are utf-8, so finding the nth character is a O(n) operation. Most people expect their indexing to be O(1) (or perhaps O(log(n)) in the worst case). In addition, indexing into a string is hardly ever a useful operation.
@Thiez Analogously to slicing (Index<Range<usize>>) and other methods such as char_indices(), the index would be a _byte_ index which must lie on a code point boundary.
As mentioned previously this is not possible when the output is char, but it is indeed possible when the output is u8. The libs team decided before 1.0, however, that we would not implement this as a str is moreso a container of char rather than a container of bytes. Adding an impl like this would be a large enough change that it would likely require an RFC, so I'm going to close this for now. RFCs are of course welcome though!
Most helpful comment
They could implement
Index<usize, Output=u8>. On the other hand, the forced choice ofs.bytes()vss.chars()raises awareness that they aren't the same.