> Can you name some examples of "frivolous sugar"?
The one mentioned in the article seemed fairly frivolous to me. I don't know if I can name one that's already been accepted into the language which I would call frivolous, per se, though they're all varying degrees of necessary. But most of the "sugar" syntaxes have made the language harder to understand for newcomers, even the ones that are arguably necessary. They all come with a cost.
The ? syntax for Results, for example, rubs me the wrong way a little bit. In that case it really does eliminate a large amount of code and is probably worth the trade-off. But now instead of Results just being a monad that can be picked apart like any other data structure, they become a Language Feature that gets special, magical treatment not expressible by the type system. You just have to know what the question mark translates to underneath. Worthwhile or not, this makes me sad. Async/await is a similar case.
> Also compile times have been a big focus of the compiler team, and have been going down YoY.
Yes but adding complexity to the language immutably increases the difficulty of that task. Even if only by a little bit, it adds debt that will have to be reckoned with for the rest of the language's lifetime.
> But now instead of Results just being a monad that can be picked apart like any other data structure, they become a Language Feature that gets special, magical treatment not expressible by the type system.
I believe, but please correct me if I'm wrong, that the try operator (`?`) does nothing which lies outside of the type system. It just transforms
let v = expr?;
into
let v = match expr {
Ok(v) => v,
Err(e) => return Err(e.into()),
};
Maybe "by the type system" was the wrong way to say that. What I meant is that if I wanted to write my own Result, say Result2, it wouldn't be included in the question mark syntax. Perhaps I could write a macro for it, I guess, but the real one is not implemented as a macro and if I wanted to go use my knowledge of the language fundamentals to read the standard library and figure out what it does, I couldn't do that. It just is that way.
This is being worked on. See the Try trait in std::ops. It's implemented for Result, Option and Poll (the `try!` macro only ever worked with Result). Implementing it for your own types is currently unstable because sorting out all the edge cases is proving to be difficult.
But the intent is definitely to stabilize it once a good general solution is found.
That's good to know. And I suppose there are other cases where "special language features" can be hooked into via the (wonderful) traits system, like Drop, so I guess that does go some way toward relieving the sting of having magical syntaxes.
'?' is an almost completely useless language feature IMO.
The second block is much clearer and uniform. When reading the first you implicitly read it as the second, which introduces mental overhead.
The only upside of having '?' is to write less code, which is the worst kind of syntactic sugar: It makes the writer type less for a couple of seconds, but the result is harder to read.
Now even if one doesn't agree with the above it is still a bad feature. Why? Because the upside of it just doesn't outweigh the cost of having any syntactic language feature like this.
And I don't just mean the energy invested in introducing it into Rust, but also the continuous cost of having to deal and respect it in future changes.
This is a bad case of hyper-optimization within a very narrow scope combined with bikeshedding.
This is all subjective of course. I for example feel the exact opposite of what you described, and I think the overwhelming majority of Rust coders prefers it to explicit matching (which I find is just code noise).
I’m not sure how much Rust code you’ve actually written, but almost uniformly everyone in the Rust community prefers ? to try! and the explicit designating that you suggest. The fact that other languages are adopting this [1] suggests that your preference is not the popular one.
And I’m pretty sure there isn’t “continuous energy” being invested in supporting this. It’s primarily a one and done feature...
I made it very clear that this is my personal opinion. I'm aware of the fact that the feature made it into the language, because it had widespread support.
I still don't think it is a good feature.
> I’m not sure how much Rust code you’ve actually written
Only as much as someone who finds time on the side to learn the language. There are many things that make this process nice, for example the compiler messages, clippy, traits, the functional API on iterators and so on.
But I've read substantially more code than I wrote. And as I stated the ? operator seems to be primarily a feature that makes writing more convenient. Not easier, not clearer, just shorter.
The pattern matching syntax expresses what it does very clearly and explicitly in a nice, tree branching like structure. And it is also documenting the code more directly.
Again, even if you and "almost uniformly everyone" disagrees with this. There is still the more general point of: How useful does a feature need to be to be considered at all? "Most people find it nicer to write" is in my opinion too weak.
> And I’m pretty sure there isn’t “continuous energy” being invested in supporting this. It’s primarily a one and done feature...
To be frank I find this to be shortsighted. Every syntactic feature adds baggage, that has to be dealt with continuously on some level. The feature already was limiting the syntactic possibilities of async/await for example, which is in my opinion a much more important and impactful feature. This is the kind of evolution that is painful to see, especially since this is a repeating pattern with evolving languages.
I like, even admire a lot of things about the language but I feel the weak point of Rust is its syntax. Especially for such a young language there are already too many ways to express the same thing. And this might be the fundamental point where we disagree.
I don't completely buy the argument for `?`. Yes, you have to know what it compiles down to, but the same goes for any other part of `std::ops` (like Deref, Index, etc.). In that way the addition of `?` as `std::ops::Try` doesn't imply "special, magical treatment not expressible by the type system", but gives it the deserved representation in the type system that was possible anyway, and hooks it up with a syntax that is only achievable with compiler support.
The one mentioned in the article seemed fairly frivolous to me. I don't know if I can name one that's already been accepted into the language which I would call frivolous, per se, though they're all varying degrees of necessary. But most of the "sugar" syntaxes have made the language harder to understand for newcomers, even the ones that are arguably necessary. They all come with a cost.
The ? syntax for Results, for example, rubs me the wrong way a little bit. In that case it really does eliminate a large amount of code and is probably worth the trade-off. But now instead of Results just being a monad that can be picked apart like any other data structure, they become a Language Feature that gets special, magical treatment not expressible by the type system. You just have to know what the question mark translates to underneath. Worthwhile or not, this makes me sad. Async/await is a similar case.
> Also compile times have been a big focus of the compiler team, and have been going down YoY.
Yes but adding complexity to the language immutably increases the difficulty of that task. Even if only by a little bit, it adds debt that will have to be reckoned with for the rest of the language's lifetime.