Live data from Hacker News

Rust's language ergonomics initiative

blog.rust-lang.org

271–280 of 295 posts

Re: Rust's language ergonomics initiative

#271
post #267

Earlier quoted context omitted.

fn main() { let s1 = "Hello, world"; // &str let s2 = String::from("Hello, world"); // String assert_eq!(s1, s2); assert_eq!(s2, s1); } compiles just fine for me?

Okay, once again I try to find an example from my code, and once again it turns out that Rust makes it simple in the simple case, but the more complex cases are still confusing. If I change the test value Some("zh".to_string()) into Some("zh"), it points to that line and tells me: expected struct `std::string::String`, found &str Sure, it's a different situation because the value is wrapped in an Option. But if Strin…

Ah yes. So this is an area where the diagnostic is _slightly_ misleading; it's trying to point out that you have two different types, and that that's the difference between the two of them. It's not that they can't be compared. Maybe a bug should be filed...

String and &str can normally be compared because of Deref, that is, &String derefs to &str. Option, on the other hand, does not implement Deref, and so no coercion happens. Rust doesn't do a lot of coercions, but Deref is one of the bigger ones.

Back to the _actual_ topic at hand, I can see how this can be a pain point until you know the rules, though. :/

Re: Rust's language ergonomics initiative

#272
post #258

Earlier quoted context omitted.

> 1. Error handling. The lack of built-in support for multi-error or error union in Result is painful in dealing with different types of error in a function. Support for Result would be helpful. Or may be support for easily converting one type of error to another. Now there's lots of boiler plate code to deal with error conversion. Error chaining would be nice, too. There are a couple of crates that support this; per…

> String has a Deref instance for &str, so taking a reference to a String automatically works as a &str. You can also call .as_str(). > > Going in the other direction, you can call .to_string() to make a copy of a &str as a new String. As a beginner in Rust myself, I would like to observe that &str vs. String problems come up all the time for me. Every one of them is quickly resolved by knowing where to add an & or a…

I absolutely agree with you, and it seems worth looking closely at the problem to see if some change would make it easier to learn. However, the ownership and borrowing system represents the single biggest innovation and key idea of Rust, as well as the thing with the least ability to apply learnings from other languages. So while we should look closely at any roadblocks that make it harder to learn than necessary, we can't make it entirely transparent.

Re: Rust's language ergonomics initiative

#273
post #267

Earlier quoted context omitted.

Okay, once again I try to find an example from my code, and once again it turns out that Rust makes it simple in the simple case, but the more complex cases are still confusing. If I change the test value Some("zh".to_string()) into Some("zh"), it points to that line and tells me: expected struct `std::string::String`, found &str Sure, it's a different situation because the value is wrapped in an Option. But if Strin…

Ah yes. So this is an area where the diagnostic is _slightly_ misleading; it's trying to point out that you have two different types, and that that's the difference between the two of them. It's not that they can't be compared. Maybe a bug should be filed... String and &str can normally be compared because of Deref, that is, &String derefs to &str. Option, on the other hand, does not implement Deref, and so no coerci…

> String and &str can normally be compared because of Deref, that is, &String derefs to &str. Option, on the other hand, does not implement Deref, and so no coercion happens.

For this particular case, any particular reason we couldn't add an impl of PartialEq? In fact, once we have specialization, couldn't we have a general impl of PartialEq for Options of Deref types?

Re: Rust's language ergonomics initiative

#274
post #156

Earlier quoted context omitted.

I really hope one day I can build a macro for ternary operator with ? and :.

Is using the if statement as a ternary that much worse? let x = if a { b } else { c }; Sure, it costs a few characters, but I appreciate the consistency and clarity.

Verbose.

Re: Rust's language ergonomics initiative

#275

Earlier quoted context omitted.

Ah yes. So this is an area where the diagnostic is _slightly_ misleading; it's trying to point out that you have two different types, and that that's the difference between the two of them. It's not that they can't be compared. Maybe a bug should be filed... String and &str can normally be compared because of Deref, that is, &String derefs to &str. Option, on the other hand, does not implement Deref, and so no coerci…

> String and &str can normally be compared because of Deref, that is, &String derefs to &str. Option, on the other hand, does not implement Deref, and so no coercion happens. For this particular case, any particular reason we couldn't add an impl of PartialEq? In fact, once we have specialization, couldn't we have a general impl of PartialEq for Options of Deref types?

  impl PartialEq> for Option where T: PartialEq
does exist, but I'm not 100% sure why Deref doesn't kick in here, I just know that it doesn't.

> couldn't we have a general impl of PartialEq for Options of Deref types?

I think the issue is None. You'd get a null pointer, which doesn't make any sense in safe rust.

Re: Rust's language ergonomics initiative

#276

Earlier quoted context omitted.

> String and &str can normally be compared because of Deref, that is, &String derefs to &str. Option, on the other hand, does not implement Deref, and so no coercion happens. For this particular case, any particular reason we couldn't add an impl of PartialEq? In fact, once we have specialization, couldn't we have a general impl of PartialEq for Options of Deref types?

impl PartialEq > for Option where T: PartialEq does exist, but I'm not 100% sure why Deref doesn't kick in here, I just know that it doesn't. > couldn't we have a general impl of PartialEq for Options of Deref types? I think the issue is None. You'd get a null pointer, which doesn't make any sense in safe rust.

> I think the issue is None. You'd get a null pointer, which doesn't make any sense in safe rust.

No, I don't mean an impl between Option and T, I mean a bidirectional impl of PartialEq between Option and Option where U is T's Deref::Target.

In that case, None doesn't cause an issue; None == None, and Some(t) == Some(u) iff *t == u

Re: Rust's language ergonomics initiative

#277

Earlier quoted context omitted.

> 10 minutes watching new users code in Rust will give you better ideas than 10 weeks thinking about the problem in your head. I'd add: Do you want to focus on new or experienced users? For example, when implementing systems that will be used 8 hrs/day by its users, we look only at efficiency for experienced users (unless the political situation requires placating the noobs). They will be noobs for a day or maybe a c…

This is the reasoning that is used for Clojure - "Clojure is for experts". It's used to rationalise all sorts of design choices that make the language much harder to get started with than (IMO of course) it should be. If you're implementing a system that users have to use for their job, they'll put up with whatever they have to while they're learning it. If you're implementing a programming language and you want to i…

I guess the optimum has to be some kind of "area under the learning curve" but I think it's pretty clear if you made a binary choice optimising for people who already made the effort makes a lot more sense. Is Clojure really that bad? I don't know it, but I never had the impression there was an anti-newbie community. Sometimes people take these binary positions as a decision-making optimisation too; having that policy just simplifies a lot of discussions, perhaps.

Re: Rust's language ergonomics initiative

#278
post #69

Earlier quoted context omitted.

In Perl, it's fairly idiomatic to use a postfix condition on a return like that when doing early return. Some of that is obviated by Rust being typed, some is not. e.g. sub compute_interest( $amount, $interest ) { return $amount if $interest == 0; # Quick return die "We don't allow computation of negative interest rates" if $interest Edit: Also, it's worth noting that Perl enforces some behavior on this by only allow…

I've always disliked this aspect of Perl... I prefer control flow to be obvious.

Hiding the actual control part on the right is pretty bad, yes.

Other than that, early returns can simplify flow a lot - otherwise you may have to do massive nesting ifs or many flags. Or even goto or exceptions.

Re: Rust's language ergonomics initiative

#279

Earlier quoted context omitted.

impl PartialEq > for Option where T: PartialEq does exist, but I'm not 100% sure why Deref doesn't kick in here, I just know that it doesn't. > couldn't we have a general impl of PartialEq for Options of Deref types? I think the issue is None. You'd get a null pointer, which doesn't make any sense in safe rust.

> I think the issue is None. You'd get a null pointer, which doesn't make any sense in safe rust. No, I don't mean an impl between Option and T, I mean a bidirectional impl of PartialEq between Option and Option where U is T's Deref::Target. In that case, None doesn't cause an issue; None == None, and Some(t) == Some(u) iff *t == u

Ah right, yes.

Re: Rust's language ergonomics initiative

#280

Earlier quoted context omitted.

I've always disliked this aspect of Perl... I prefer control flow to be obvious.

Hiding the actual control part on the right is pretty bad, yes. Other than that, early returns can simplify flow a lot - otherwise you may have to do massive nesting ifs or many flags. Or even goto or exceptions.

It's less bad than it seems, since it's a common idiom in Perl, so you're used to looking at it. It can be quite bad if abused, but so can so much in Perl.

When used with a return or die (or my personal favorite for debugging with 'warn "FOO" if $ENV{DEBUG};"), the fact that flow is affected is obvious by the very first characters in the statement, so it's obvious to then look for when it applies.

Like so many features of languages, how it looks from the outside compared to how it looks from those that are well versed in the language can be quite different (not to say that everything that looks like a wart in Perl is okay once you get used to it, every language has real warts). That's another aspect to this whole thing, how much to you emphasize ergonomics that are primarily for learning and novices. Features focused at novices to the expense of those familiar with the language are interesting, because they may draw a lot of people to your language, but you may not retain them very well.

Post reply on HN