Introduction
Rust has currently acquired sufficient writing ease and productivity. But as much as I love the language, I’m writing this article to highlight some things I find annoying. Indeed one of the main concerns of the language is to please newcomers, and I find, that on this point there has been a lot of progress made (ex: NLL) but there is still work to do. So this is a critic with some open questions because I haven’t found or I found few proposals to this kind of features.
Here I won’t talk about well-known features that are missing from the ecosystem. But many things that I found awkward and possible improvements inspired by other languages.
Disclaimer, this post is highly biaised, this post highligh things where I struggled when learning rust. I might propose some syntax changes but I only want to share the idea and not the “syntax” part.
Copy types
For beginners, I find it’s complicated to understand the move semantic and therefore the clone and copy. The problem is that you can’t know if you’re manipulating a type that’s Copy or not, and that’s affecting the mental model of the program. Paradoxical for a language where everything must be explicit. Even if the practice makes it possible to know, it makes the programming error prone. Unfortunately I don’t see a way to make it more explicit, except to make it obvious with a different font or syntax coloring.
Verbosity
’?’ for Option
Why can’t we use ‘?’ For parameters that can be None, the function signatures are lengthened and the returns too. When it could just be like this :
fn test_with_new_option(option : A? ) -> B? {
option?.b
}
I thinks this is quite good and readable, It can be extended to handle Result<T,Err> IMO it’s more clunky.
fn test_with_new_result(res : A?Err) -> B?Err {
res?.b
}
Implied bounds
When you write generic struct, bounded by certain trait you have to repeat the bounds on every impl of the struct. There is an RFC but it’s blocked.
Auto wrapping ()
Sorry but returning Some(())
feels weird and unecessary. Maybe we can coherce Some(())
to Some
or Some()
. I know there is some work on the rails for auto wrappring and try blocks so w’ll see.
fn return_empty_options() -> Option<()> {
Some // My preference
}
fn return_empty_options() -> Option<()> {
Some()
}
fn return_ok() -> Result<(), Err> {
Ok
}
It can by combine with the ‘?’ syntax sugar.
fn return_with_sugar() -> ()? {
Some
}
fn return_ok_with_sugar() -> ()?Err {
Ok
}
Mono parameter closures
The closures that take only one parameter, we could easily omit the |param|
and use a default name, it would reduce a lot of code. Inspired by Kotlin. They will be corner cases when we want to pattern match the parameter. But the most common cases will be handled (I suppose) ?
fn closure_ref(elements : impl Iterator<Item=A>) -> usize {
elements
// &A
.map(it.b)
// &B
.map(it.c)
// &C
.filter_by(it.key)
}
fn closure_move(elements : impl Iterator<Item=A>) -> usize {
elements
// A
.map(move it.b)
// B
.map(move it.c)
// C
.filter_by(move it.key)
}
Awkward things
- String and &str. Easy to get it, but the naming is confusing.
- static and const. Naming confusing because const is more like “inline value”.
- Some funciton take references and anothers copy on the same struct, while the type is copy. Example char type
- Copy structs are always a shallow copy but
[0u8; 10000]
is copy but it’s not shallow. - IntoIter for arrays it’s an iterator by reference. Issue., while IntoIter for Vec
is by move.
Open questions.
Const functions
Here I’m just going to ask an open question as this is the first time I’ve done this kind of exercise.
Why are we going to do the same thing as C++ and add “const” (constexpr for C++) to all functions. Why is const not the default behavior since all functions will eventually be const, I understand that it’s a contract between the user and the library developer but still. It’s like the decision to make immutability by default, we should also have had “const” by default, because only functions with IO will not be const ?.