-
Notifications
You must be signed in to change notification settings - Fork 14k
Implement MutableSeq for String #16040
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Unsure why the Travis build stalled. |
|
If accepted this needs to retain the |
|
Ah my bad, |
|
Note that the policy is not just adding "breaking-change" to the commit message, in particular:
as well as
In short, this change needs to preserve the two functions with a |
|
I'm not convinced it makes sense for I guess this isn't really a strong objection, and it's primarily motivated by the fact that I don't like using Is there any actual use-case for having |
|
Sorry for the delay, vim lost my commit message the first time. The primary rationale is that because |
|
Added |
|
Nitpick: it behaves as a collection of Unicode scalar values. Also, let mut s = String::new();
assert_eq!(s.len(), 0);
s.push_char('\u2022');
s.push_char('\U0001F419');
assert_eq!(s.len(), 2); // FAILSOne would normally expect a collection's I think this is actually a big enough issue that |
|
@kballard Good point. Maybe It's worth noting that the two other collection traits of |
|
That ship sailed a long time ago. We can't make len() return scalar values without changing nearly the entire API, and breaking all the current performance guarantees. Performance is the biggest reason why our String API is primarily byte-focused, and that's important to a lot of people. If you have a real need for a MutableSeq String you could experiment with creating a newtype wrapper that provides this. |
|
I figured as much. The other alternative would be to have You mean with |
|
It doesn't make sense for
No, you can't derive // this is a tuple struct because clients only construct these and
// we like the tuple struct construction form
pub struct StringSeq<'a>(&'a mut String);
impl<'a> StringSeq<'a> {
fn inner_mut(&mut self) -> &mut String {
let StringSeq(&ref mut s) = *self;
s
}
fn inner(&self) -> &String {
let StringSeq(&ref s) = *self;
s
}
}
impl<'a> MutableSeq<char> for StringSeq<'a> {
#[inline]
fn push(&mut self, value: char) {
self.inner_mut().push_char(value)
}
#[inline]
fn pop(&mut self) -> Option<char> {
self.inner_mut().pop_char()
}
}
impl<'a> Mutable for StringSeq<'a> {
#[inline]
fn clear(&mut self) {
self.inner_mut().clear()
}
}
impl<'a> Collection for StringSeq<'a> {
#[inline]
fn len(&self) -> uint {
self.inner().len()
}
#[inline]
fn is_empty(&self) -> bool {
self.inner().is_empty()
}
}
fn replace_last<T, S: MutableSeq<T>>(seq: &mut S, val: T) {
if seq.pop().is_some() {
seq.push(val)
}
}This is then usable like so: fn replace_last<T, S: MutableSeq<T>>(seq: &mut S, val: T) {
if seq.pop().is_some() {
seq.push(val)
}
}
fn main() {
let mut s = String::from_str("this works?");
replace_last(&mut StringSeq(&mut s), '!');
assert_eq!(s.as_slice(), "this works!");
} |
Isn't it possible to push and pop bytes with I see the appeal of exposing byte-interfaces. Is there any particular code in Rust's libraries that relies on an O(1) guarantee from |
|
@alexchandel
I don't know, but it absolutely is the default assumption by effectively all potential |
I'd be in favor of that.
I probably wouldn't assume Although you're right, String carries the properties of both a sequence of bytes and chars enough that it would be misleading to do this. I have a better idea: would these |
|
@alexchandel What would be the purpose of pulling these out into a |
@kballard Then let's delete StrSlice, UnicodeStrSlice, MutableVector, MutableVectorAllocating, ImmutableVector, VectorVector, ImmutableEqVector, ImmutableOrdVector, MutableCloneableVector, MutableByteVector, ImmutableCloneableVector, MutableVectorAllocating, MutableOrdVector, Char, UnicodeChar, UpdateIoError, BoxAny, and every other trait with only a single implementation. Frankly that's a terrible argument. The fact that those methods form a coherent, composable unit of behavior is reason enough to factor them into a trait. Dividing the functionality of such a ubiquitous type into traits lends additional clarity to the API. And even if no other rust type implements |
|
The only reason those traits exist is because they're adding methods to built-in types and you can't add methods to built-in types without a trait. There's also a chance that in the future we'll change the rules to allow libstd to define methods on built-in types so we can get rid of them. The only exceptions in your list are
That is not the general philosophy of the Rust standard library. Methods are only put into traits when either
Moving methods into a trait actually makes it harder for people to find in the documentation where a method comes from, makes it harder to call the method if they don't have the trait in scope, and bloats the prelude with more and more traits. |
|
I'm convinced this isn't the right trait for String to implement. @kballard Thank you for your feedback! |
|
This issue deserves further consideration, given that In particular, the complaint:
is now manifestly untrue. |
|
Despite |
…ust-lang#16040) Closes rust-lang/rust-clippy#16026 changelog: [`missing_asserts_for_indexing`] fix wrongly changing `assert_eq` to `assert`
This moves the
Stringmethodspush_charandpop_charunder aMutableSeq<char>implementation and renames them topushandpoprespectively. This is appropriate given String's UTF-8 guarantee, and the existing parallels between String and Vec.