Re: [rust-dev] PSA: ~string is probably not what you want
On Tue, Apr 30, 2013 at 9:22 PM, Graydon Hoare gray...@mozilla.com wrote: On 30/04/2013 11:26 AM, Gábor Lehel wrote: Couldn't this be relaxed? In other words allow dynamically sized `str` as a type (and perhaps similarly for other dynamically sized types), but prohibit those things specifically which would be problematic, i.e. using it in ways that would require knowing its size? This option was considered at ... great length, a year ago during the vector-reform conversations. https://mail.mozilla.org/pipermail/rust-dev/2012-April/001742.html https://mail.mozilla.org/pipermail/rust-dev/2012-April/001772.html https://mail.mozilla.org/pipermail/rust-dev/2012-June/001951.html https://mail.mozilla.org/pipermail/rust-dev/2012-July/002114.html I'm not sure anyone ever reduced those threads to their essence, but re-reading them I think I can articulate the fundamental difficulty with what you're suggesting: - Any object has a real size. Some sizes are statically known, some must be discovered dynamically (by reading a size field or carrying a size value in a (ptr,size) pair) - When T is static-size, T and ~T and @T should be 1-word pointers. The compiler knows the size. - To operate on a vector of statically-unknown size, you need to get its dynamically-known size from somewhere. This means pointers to vectors need to carry bounds. - So ~[] and @[] and [] are not the same representation as ~T, @T and T in general. They have to have a size stuck on them somewhere. - We want to be able to take sub-slices and have slices that point to fixed-size vectors in C structs. This means slices can't have their length in the pointee, and have to be (ptr,len) pairs. So about the only wiggle room away from where we are now is that we might be able to make ~[] represented by (ptr,len) pairs too, like slices are, rather than 1 ptr that points to a [len,data...] buffer. But it's not clear if that would buy us anything. Maybe a bit more genericity in impls, though I don't know how; Niko might. There might be a bit more room for improvement here, but it's an _extremely_ constrained space to work in. -Graydon Thanks for the explanation! That makes a lot of sense. I also just read Niko's blog post, and I'm not sure which thread to reply in (or who to reply to), but I guess I'll do it here. Niko's message here beforehand was kind of expectations-downplaying, but reading the blog post, his proposed scheme seems to allow more or less the same as what I was asking about here (perhaps minus the user-defined dynamically sized types, but that was icing). So *if* the plan ends up working out, then taking the second part of my earlier proposal: You might also have a rule whereby dereferencing a variable when the result would be a dynamically-sized type is allowed *if* the result is immediately borrowed. Then instead of `impl Eq for {@str, ~str, str}`, you would have just `impl Eq for str`, and if you want to compare an ~str you dereference it. Would that work? Would it be a good solution? -- Your ship was destroyed in a monadic eruption. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On Wed, May 01, 2013 at 02:39:12PM +0200, Gábor Lehel wrote: I also just read Niko's blog post, and I'm not sure which thread to reply in (or who to reply to), but I guess I'll do it here. Niko's message here beforehand was kind of expectations-downplaying, but reading the blog post, his proposed scheme seems to allow more or less the same as what I was asking about here (perhaps minus the user-defined dynamically sized types, but that was icing). Yeah, I wasn't sure how well that idea of changing the representation for all vecs/strings would work out, but then in the process of writing the post I decided it worked out quite well. It was an idea I first had last summer when we were hashing this out the first time, and have been meaning to chew on for some time, so I'm glad we had this thread on the mailing list to bring it back to my mind. So *if* the plan ends up working out, then taking the second part of my earlier proposal: You might also have a rule whereby dereferencing a variable when the result would be a dynamically-sized type is allowed *if* the result is immediately borrowed. Then instead of `impl Eq for {@str, ~str, str}`, you would have just `impl Eq for str`, and if you want to compare an ~str you dereference it. Would that work? Would it be a good solution? I believe that would be the plan, yes. Most of these apply-to-almost-everything traits, like `Eq` or `Ord`, could be implemented in a similar fashion. I'm not sure what problem you are proposing this as a solution *for*, though. Do you mean the problem of comparing strings using `==`? I suppose it is true that under this proposal you could write let str1: ~str = ~hi; let str2: str = hi; *str1 == *str2 and it would work fine. That is a nice side-effect I hadn't considered. *An aside:* Note that dereferencing a pointer to an unsized object is only allowed in an lvalue context (that is, when we are taking its address): let str1: ~str = ~hi; let foo = *str1; // ERROR let bar = *str1; // OK Here, `foo` is an error because `*str1` is being evaluated in an rvalue context, but `bar` is fine, because `*str1` is being evaluted in an lvalue context. In the case of `==`, this works out because the arguments to overloaded operators are always passed by reference. *A further aside:* don't be misled by my use of the term lvalue context into thinking that a program like this would be legal: let mut str1: ~str = ~Hello; *str1 = World; // ERROR This is illegal because assigning to an lvalue of unsized type is illegal, even though `*str1` appears in an lvalue context. regards, Niko ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On Wed, May 1, 2013 at 4:50 PM, Niko Matsakis n...@alum.mit.edu wrote: On Wed, May 01, 2013 at 02:39:12PM +0200, Gábor Lehel wrote: So *if* the plan ends up working out, then taking the second part of my earlier proposal: You might also have a rule whereby dereferencing a variable when the result would be a dynamically-sized type is allowed *if* the result is immediately borrowed. Then instead of `impl Eq for {@str, ~str, str}`, you would have just `impl Eq for str`, and if you want to compare an ~str you dereference it. Would that work? Would it be a good solution? I believe that would be the plan, yes. Most of these apply-to-almost-everything traits, like `Eq` or `Ord`, could be implemented in a similar fashion. I'm not sure what problem you are proposing this as a solution *for*, though. Do you mean the problem of comparing strings using `==`? Yeah. Which was the original topic of this thread... :) I suppose it is true that under this proposal you could write let str1: ~str = ~hi; let str2: str = hi; *str1 == *str2 and it would work fine. That is a nice side-effect I hadn't considered. Right. That was the intent. And similarly(?) for comparing against string literals. (Though I'm not completely clear about when auto-borrowing does or doesn't happen, and how that would interact with this.) *An aside:* Note that dereferencing a pointer to an unsized object is only allowed in an lvalue context (that is, when we are taking its address): let str1: ~str = ~hi; let foo = *str1; // ERROR let bar = *str1; // OK Here, `foo` is an error because `*str1` is being evaluated in an rvalue context, but `bar` is fine, because `*str1` is being evaluted in an lvalue context. In the case of `==`, this works out because the arguments to overloaded operators are always passed by reference. Yep, that's what I was figuring. I'm not sure what lvalue context means precisely -- it's not actually on the left hand side of anything here, and the other example below where it *is* on the LHS is illegal -- but the shape of things matches what I was expecting. *A further aside:* don't be misled by my use of the term lvalue context into thinking that a program like this would be legal: let mut str1: ~str = ~Hello; *str1 = World; // ERROR This is illegal because assigning to an lvalue of unsized type is illegal, even though `*str1` appears in an lvalue context. Hmm. If I'm thinking right this is because the size of the string is stored in the pointer, which, if the string gets changed behind its back, would become invalid? regards, Niko -- Your ship was destroyed in a monadic eruption. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On Sun, Apr 28, 2013 at 8:14 PM, Patrick Walton pwal...@mozilla.com wrote: Is there some way to make it just work, no matter what kind of strings you're comparing? Perhaps foo == (*x) would work, for example? That doesn't work, because it makes the dynamically sized `str` a type, which is incoherent. (It would lead to dynamically sized stack frames, or structs or enums with infinite size, and so on.) Couldn't this be relaxed? In other words allow dynamically sized `str` as a type (and perhaps similarly for other dynamically sized types), but prohibit those things specifically which would be problematic, i.e. using it in ways that would require knowing its size? I think this would essentially mean no variables, members, or parameters of that type, but you *could* use it as a type argument -- including to the various pointer type constructors. You might also have a rule whereby dereferencing a variable when the result would be a dynamically-sized type is allowed *if* the result is immediately borrowed. Then instead of `impl Eq for {@str, ~str, str}`, you would have just `impl Eq for str`, and if you want to compare an ~str you dereference it. Which seems logical to me, after all ostensibly you want to compare the contents and not the pointer. -- Your ship was destroyed in a monadic eruption. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On 4/30/13 11:26 AM, Gábor Lehel wrote: Couldn't this be relaxed? In other words allow dynamically sized `str` as a type (and perhaps similarly for other dynamically sized types), but prohibit those things specifically which would be problematic, i.e. using it in ways that would require knowing its size? I think this would essentially mean no variables, members, or parameters of that type, but you *could* use it as a type argument -- including to the various pointer type constructors. Unfortunately that doesn't work, because opaque type variables `T` can still be moved, including into the local stack frame. Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On Tue, Apr 30, 2013 at 8:27 PM, Patrick Walton pwal...@mozilla.com wrote: On 4/30/13 11:26 AM, Gábor Lehel wrote: Couldn't this be relaxed? In other words allow dynamically sized `str` as a type (and perhaps similarly for other dynamically sized types), but prohibit those things specifically which would be problematic, i.e. using it in ways that would require knowing its size? I think this would essentially mean no variables, members, or parameters of that type, but you *could* use it as a type argument -- including to the various pointer type constructors. Unfortunately that doesn't work, because opaque type variables `T` can still be moved, including into the local stack frame. This did actually occur to me while writing the previous, along with early thoughts about what you could do about it, but I thought I wouldn't get too far ahead of myself. My thought process so far has been: - OK, so maybe you would need a new built-in trait to track it, say StaticSized, which you would need if you want to do that kind of thing with a type variable. - But that's the *common* case. You would have to write StaticSized everywhere! Clearly that's not viable. - OK, so maybe there's a way to invert it? ...but that doesn't really make any sense, after half a minute of reflection. - What about inference? The compiler checks how the type parameter is used, and if it's used in way that requires knowing its size, the compiler puts an implicit must be statically sized constraint on it, after which instantiating it with a dynamically sized type produces an error at the point of instantiation. (Not having it be obvious in the source at the point of declaration whether a type variable is allowed to be dynamically sized would be an annoyance, but I think a minor one. In the generated documentation it could maybe be indicated by italics, or their absence.) So that's where I am right now. What about inference? (I recall reading that co/contravariance is also handled by inference, but I don't know if that has any parallels with this beyond the superficial.) Another thing this might allow is user-defined dynamically sized types. Putting a dynamically sized type as the last member of a struct or enum variant would be allowed (as per the common C idiom), in which case the struct or enum itself would be considered dynamically sized, and have the same rules apply. -- Your ship was destroyed in a monadic eruption. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On 30/04/2013 11:26 AM, Gábor Lehel wrote: Couldn't this be relaxed? In other words allow dynamically sized `str` as a type (and perhaps similarly for other dynamically sized types), but prohibit those things specifically which would be problematic, i.e. using it in ways that would require knowing its size? This option was considered at ... great length, a year ago during the vector-reform conversations. https://mail.mozilla.org/pipermail/rust-dev/2012-April/001742.html https://mail.mozilla.org/pipermail/rust-dev/2012-April/001772.html https://mail.mozilla.org/pipermail/rust-dev/2012-June/001951.html https://mail.mozilla.org/pipermail/rust-dev/2012-July/002114.html I'm not sure anyone ever reduced those threads to their essence, but re-reading them I think I can articulate the fundamental difficulty with what you're suggesting: - Any object has a real size. Some sizes are statically known, some must be discovered dynamically (by reading a size field or carrying a size value in a (ptr,size) pair) - When T is static-size, T and ~T and @T should be 1-word pointers. The compiler knows the size. - To operate on a vector of statically-unknown size, you need to get its dynamically-known size from somewhere. This means pointers to vectors need to carry bounds. - So ~[] and @[] and [] are not the same representation as ~T, @T and T in general. They have to have a size stuck on them somewhere. - We want to be able to take sub-slices and have slices that point to fixed-size vectors in C structs. This means slices can't have their length in the pointee, and have to be (ptr,len) pairs. So about the only wiggle room away from where we are now is that we might be able to make ~[] represented by (ptr,len) pairs too, like slices are, rather than 1 ptr that points to a [len,data...] buffer. But it's not clear if that would buy us anything. Maybe a bit more genericity in impls, though I don't know how; Niko might. There might be a bit more room for improvement here, but it's an _extremely_ constrained space to work in. -Graydon ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On Tue, Apr 30, 2013 at 12:22:15PM -0700, Graydon Hoare wrote: So about the only wiggle room away from where we are now is that we might be able to make ~[] represented by (ptr,len) pairs too, like slices are, rather than 1 ptr that points to a [len,data...] buffer. But it's not clear if that would buy us anything. Maybe a bit more genericity in impls, though I don't know how; Niko might. There might be a bit more room for improvement here, but it's an _extremely_ constrained space to work in. I've been working on a blog post about this. I'm not yet sure if it buys us anything. I'll try to finish that up and get it out. But basically everything you said is true, particularly that last sentence! Niko ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
Hi Graydon, How does Rust currently represent its' pointers to vectors? Based on what I've seen in the library, it seems that ~[T] and @[T] are plain pointers (with size stored in the pointee), but [T] is a fat pointer, i.e. a (ptr,len) pair. Is this correct? On Tue, Apr 30, 2013 at 12:22 PM, Graydon Hoare gray...@mozilla.com wrote: On 30/04/2013 11:26 AM, Gábor Lehel wrote: Couldn't this be relaxed? In other words allow dynamically sized `str` as a type (and perhaps similarly for other dynamically sized types), but prohibit those things specifically which would be problematic, i.e. using it in ways that would require knowing its size? This option was considered at ... great length, a year ago during the vector-reform conversations. https://mail.mozilla.org/**pipermail/rust-dev/2012-April/**001742.htmlhttps://mail.mozilla.org/pipermail/rust-dev/2012-April/001742.html https://mail.mozilla.org/**pipermail/rust-dev/2012-April/**001772.htmlhttps://mail.mozilla.org/pipermail/rust-dev/2012-April/001772.html https://mail.mozilla.org/**pipermail/rust-dev/2012-June/**001951.htmlhttps://mail.mozilla.org/pipermail/rust-dev/2012-June/001951.html https://mail.mozilla.org/**pipermail/rust-dev/2012-July/**002114.htmlhttps://mail.mozilla.org/pipermail/rust-dev/2012-July/002114.html I'm not sure anyone ever reduced those threads to their essence, but re-reading them I think I can articulate the fundamental difficulty with what you're suggesting: - Any object has a real size. Some sizes are statically known, some must be discovered dynamically (by reading a size field or carrying a size value in a (ptr,size) pair) - When T is static-size, T and ~T and @T should be 1-word pointers. The compiler knows the size. - To operate on a vector of statically-unknown size, you need to get its dynamically-known size from somewhere. This means pointers to vectors need to carry bounds. - So ~[] and @[] and [] are not the same representation as ~T, @T and T in general. They have to have a size stuck on them somewhere. - We want to be able to take sub-slices and have slices that point to fixed-size vectors in C structs. This means slices can't have their length in the pointee, and have to be (ptr,len) pairs. So about the only wiggle room away from where we are now is that we might be able to make ~[] represented by (ptr,len) pairs too, like slices are, rather than 1 ptr that points to a [len,data...] buffer. But it's not clear if that would buy us anything. Maybe a bit more genericity in impls, though I don't know how; Niko might. There might be a bit more room for improvement here, but it's an _extremely_ constrained space to work in. -Graydon __**_ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/**listinfo/rust-devhttps://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On 30/04/2013 2:03 PM, Vadim wrote: Hi Graydon, How does Rust currently represent its' pointers to vectors? Based on what I've seen in the library, it seems that ~[T] and @[T] are plain pointers (with size stored in the pointee), but [T] is a fat pointer, i.e. a (ptr,len) pair. Is this correct? Correct. And [T, ..N] is N copies of T laid out in memory as a not-pointer-indirect value. -Graydon ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] PSA: ~string is probably not what you want
Just thought I'd give the mailing list a heads up that ~string, besides being ugly, is generally inefficient: it allocates a string on the heap and frees it when it goes out of scope. There are no optimizations that eliminate the allocation. If you need to compare a `~str` against a constant string, use .equiv(): use core::cmp::Equiv; fn main() { let x = ~foo; if foo.equiv(x) { println(yep); } } This should admittedly be imported by default. Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On 28/04/13 18:45, Patrick Walton wrote: If you need to compare a `~str` against a constant string, use .equiv(): use core::cmp::Equiv; fn main() { let x = ~foo; if foo.equiv(x) { println(yep); } } This should admittedly be imported by default. Really? Strings can't just be compared with == ? To be honest, that alone is almost enough to put me off the language -- not only is it ugly and unwieldy, but it suggests a lot of limitations in the language's memory model / type system / operator overloading, which would also make my own code ugly and unwieldy. What's the problem with ==, or the difference with equiv(), exactly? Is there some way to make it just work, no matter what kind of strings you're comparing? Perhaps foo == (*x) would work, for example? -- Lee ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On 4/28/13 10:57 AM, Lee Braiden wrote: Really? Strings can't just be compared with == ? To be honest, that alone is almost enough to put me off the language -- not only is it ugly and unwieldy, but it suggests a lot of limitations in the language's memory model / type system / operator overloading, which would also make my own code ugly and unwieldy. What's the problem with ==, or the difference with equiv(), exactly? The problem is that `str` and `~str` are not the same type. We could change `Eq` so that it doesn't require the same type on the left-hand-side and the right-hand-side, but that would complicate the trait system quite a bit. Currently, overloaded operators do not borrow. I guess we could change overloaded operators (or maybe just `==` and `!=`?) to try to borrow the left hand side and/or right hand side to make the types match. I think this is *probably* OK. However, we need to be careful, because it's exactly the kind of thing that could have unforeseen consequences. Strings should be comparable with `==` without allocating is the kind of thing that is obviously true, but trying to do it without thinking carefully about the ramifications of borrowing in overloaded operators is problematic. We already have quite complex method lookup semantics exactly to make things like this just work, and it has fallout when you start having to get picky about how many dereferences you do. To be honest, the tone of your message is a little frustrating, because you jumped on one thing that's not ideal (that the different types `~str` and `str` cannot be compared with `==`), said something inaccurate (that strings cannot be compared with `==`), and extrapolated it to the idea that Rust's type system is ugly and unwieldy. No, it's just that we need to think carefully about how to handle this one case. Is there some way to make it just work, no matter what kind of strings you're comparing? Perhaps foo == (*x) would work, for example? That doesn't work, because it makes the dynamically sized `str` a type, which is incoherent. (It would lead to dynamically sized stack frames, or structs or enums with infinite size, and so on.) Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On Sun, Apr 28, 2013 at 1:57 PM, Lee Braiden leebr...@gmail.com wrote: On 28/04/13 18:45, Patrick Walton wrote: If you need to compare a `~str` against a constant string, use .equiv(): use core::cmp::Equiv; fn main() { let x = ~foo; if foo.equiv(x) { println(yep); } } This should admittedly be imported by default. Really? Strings can't just be compared with == ? To be honest, that alone is almost enough to put me off the language -- not only is it ugly and unwieldy, but it suggests a lot of limitations in the language's memory model / type system / operator overloading, which would also make my own code ugly and unwieldy. What's the problem with ==, or the difference with equiv(), exactly? Is there some way to make it just work, no matter what kind of strings you're comparing? Perhaps foo == (*x) would work, for example? -- Lee Strings and vectors are special cased in the syntax, ~foo and ~(foo) aren't the same type. This issue is specific to the string/vector implementations included in the language, it's a non-issue with borrowed pointers or owned/shared boxes. Eq doesn't take a type parameter for the right-hand side parameter, so if ~str is on the left-hand side the right-hand side has to be ~str too. Although a ~str can be borrowed as a slice so foo == ~foo *will* work. Eq *could* take a type parameter like Add, Sub, etc. - it just doesn't right now. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
It is very easy to create a language that is unwieldy, but hard to create something KISS simple that can be adopted, and that will be praised for its cleanliness and elegance.If the basic things are not simple, a language will be relegated to academia, and will not be as popular as hoped.We really need to take a look into this one, and come up with something workable. That won't be easy considering what Patrick has mentioned. Sent from my BlackBerry 10 smartphone.From: rust-dev-requ...@mozilla.orgSent: Monday, 29 April, 2013 3:00 AMTo: rust-dev@mozilla.orgReply To: rust-dev@mozilla.orgSubject: Rust-dev Digest, Vol 34, Issue 92Send Rust-dev mailing list submissions to rust-dev@mozilla.orgTo subscribe or unsubscribe via the World Wide Web, visit https://mail.mozilla.org/listinfo/rust-devor, via email, send a message with subject or body 'help' to rust-dev-requ...@mozilla.orgYou can reach the person managing the list at rust-dev-ow...@mozilla.orgWhen replying, please edit your Subject line so it is more specificthan "Re: Contents of Rust-dev digest..."Today's Topics: 1. PSA: ~"string" is probably not what you want (Patrick Walton) 2. Re: PSA: ~"string" is probably not what you want (Lee Braiden) 3. Re: PSA: ~"string" is probably not what you want (Patrick Walton) 4. Re: PSA: ~"string" is probably not what you want (Daniel Micay)--Message: 1Date: Sun, 28 Apr 2013 10:45:04 -0700From: Patrick Walton pwal...@mozilla.comTo: "rust-dev@mozilla.org" rust-dev@mozilla.orgSubject: [rust-dev] PSA: ~"string" is probably not what you wantMessage-ID: 517d6020.9080...@mozilla.comContent-Type: text/plain; charset=ISO-8859-1; format=flowedJust thought I'd give the mailing list a heads up that ~"string", besides being ugly, is generally inefficient: it allocates a string on the heap and frees it when it goes out of scope. There are no optimizations that eliminate the allocation.If you need to compare a `~str` against a constant string, use .equiv(): use core::cmp::Equiv; fn main() { let x = ~"foo"; if "foo".equiv(x) { println("yep"); } }This should admittedly be imported by default.Patrick--Message: 2Date: Sun, 28 Apr 2013 18:57:38 +0100From: Lee Braiden leebr...@gmail.comTo: rust-dev@mozilla.orgSubject: Re: [rust-dev] PSA: ~"string" is probably not what you wantMessage-ID: 517d6312.7030...@gmail.comContent-Type: text/plain; charset=ISO-8859-1; format=flowedOn 28/04/13 18:45, Patrick Walton wrote: If you need to compare a `~str` against a constant string, use .equiv(): use core::cmp::Equiv; fn main() { let x = ~"foo"; if "foo".equiv(x) { println("yep"); } } This should admittedly be imported by default.Really? Strings can't just be compared with == ? To be honest, that alone is almost enough to put me off the language -- not only is it ugly and unwieldy, but it suggests a lot of limitations in the language's memory model / type system / operator overloading, which would also make my own code ugly and unwieldy.What's the problem with ==, or the difference with equiv(), exactly? Is there some way to make it just work, no matter what kind of strings you're comparing? Perhaps "foo" == (*x) would work, for example?-- Lee--Message: 3Date: Sun, 28 Apr 2013 11:14:13 -0700From: Patrick Walton pwal...@mozilla.comTo: rust-dev@mozilla.orgSubject: Re: [rust-dev] PSA: ~"string" is probably not what you wantMessage-ID: 517d66f5.1020...@mozilla.comContent-Type: text/plain; charset=ISO-8859-1; format=flowedOn 4/28/13 10:57 AM, Lee Braiden wrote: Really? Strings can't just be compared with == ? To be honest, that alone is almost enough to put me off the language -- not only is it ugly and unwieldy, but it suggests a lot of limitations in the language's memory model / type system / operator overloading, which would also make my own code ugly and unwieldy. What's the problem with ==, or the difference with equiv(), exactly?The problem is that `str` and `~str` are not the same type. We could change `Eq` so that it doesn't require the same type on the left-hand-side and the right-hand-side, but that would complicate the trait system quite a bit.Currently, overloaded operators do not borrow. I guess we could change overloaded operators (or maybe just `==` and `!=`?) to try to borrow the left hand side and/or right hand side to make the types match. I think this is *probably* OK. However, we need to be careful, because it's exactly the kind of thing that could have
Re: [rust-dev] PSA: ~string is probably not what you want
On 4/28/13 12:45 PM, her...@gmail.com wrote: It is very easy to create a language that is unwieldy, but hard to create something KISS simple that can be adopted, and that will be praised for its cleanliness and elegance. If the basic things are not simple, a language will be relegated to academia, and will not be as popular as hoped. We really need to take a look into this one, and come up with something workable. That won't be easy considering what Patrick has mentioned. As Daniel pointed out, it isn't so bad. I didn't realize that we already borrow on the left hand side, so you can write: fn main() { let x = ~foo; if foo == x { println(yep); } } We just need to borrow on the right hand side too, so that `x == foo` works. I can think of ways to do it; none are particularly pretty, but I suspect we could make it work. But the situation is not so dire now. Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
Le 28/04/2013 21:49, Patrick Walton a écrit : As Daniel pointed out, it isn't so bad. I didn't realize that we already borrow on the left hand side, so you can write: fn main() { let x = ~foo; if foo == x { println(yep); } } Using `if constant == variable` rather than the reverse is sometimes called a Yoda condition and considered bad style, but that’s purely aesthetic. It’s still good that this works as expected. We just need to borrow on the right hand side too, so that `x == foo` works. I can think of ways to do it; none are particularly pretty, but I suspect we could make it work. But the situation is not so dire now. Is there a reason that both sides of the == operator should not behave the same? Like many operators == seems like it should be symmetric, ie. a == b are always the same for any a and b (and their types, presumably.) Cheers, -- Simon Sapin ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
On Sun, Apr 28, 2013 at 10:45 AM, Patrick Walton pwal...@mozilla.comwrote: If you need to compare a `~str` against a constant string, use .equiv(): I have some code where I'm trying to match an owned string against a set of constant strings, and it's not clear to me how to take your advice there. fn match_upper(to_match: str) - int { match to_match.to_ascii().to_upper().to_str_ascii() { ~ABC = 1, ~DEF = 2, ~GHI = 3, _ = 0 } } Does each call to this function heap-allocate all the owned strings in the match expression? If so, how could I avoid that? Is there a more idiomatic way to do what I'm trying to do? Thanks for the PSA, Mitch ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
In which case, would special-casing == and !=, as you mentioned earlier, be a bad thing to do? (Sincere question; from a user pov it would make sense, but I don't know whether it would make operator overloading conceptually more ugly to have that special case in there) martin On Sun, Apr 28, 2013 at 12:49 PM, Patrick Walton pwal...@mozilla.com wrote: On 4/28/13 12:45 PM, her...@gmail.com wrote: It is very easy to create a language that is unwieldy, but hard to create something KISS simple that can be adopted, and that will be praised for its cleanliness and elegance. If the basic things are not simple, a language will be relegated to academia, and will not be as popular as hoped. We really need to take a look into this one, and come up with something workable. That won't be easy considering what Patrick has mentioned. As Daniel pointed out, it isn't so bad. I didn't realize that we already borrow on the left hand side, so you can write: fn main() { let x = ~foo; if foo == x { println(yep); } } We just need to borrow on the right hand side too, so that `x == foo` works. I can think of ways to do it; none are particularly pretty, but I suspect we could make it work. But the situation is not so dire now. Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
Really? Strings can't just be compared with == ? To be honest, that alone is almost enough to put me off the language -- not only is it ugly and unwieldy, but it suggests a lot of limitations in the language's memory model / type system / operator overloading, which would also make my own code ugly and unwieldy. This kind of faux outrage isn't really constructive. Most systems languages don't let you compare strings with ==. In C you use str*cmp as == is pointer equality. This is also true in Java where you must write `if (foo.equals(bar))`. It would certainly be nice to follow in C++'s footsteps where std::strings are comparable with ==, but I'm not sure it nullifies Rust's goals if this condition can't be met. Equality always seems to be a mixed bag. In JavaScript you have == and ===. In Erlang you have == and =:=. In Java you have == and .equals(). In Clojure you have = and ==. Lisps have all kinds of things. In many cases you can end up with asymmetry that violates people's mathemeatical expectations of equality (Clojure's == is only commutative when used with two args, with 3 it gets slightly weird). jack. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] PSA: ~string is probably not what you want
Ruby is one example of a language where == is not symmetric. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev