What do you dislike about Rust?

For me it’s the semicolon, because I stopped using a semicolon in JavaScript, two other of my favorite languages, Elixir and Go don’t have a delimiter already. Before that I used Ruby (Rails) and that too didn’t have a delimiter.
So having a compulsory delimiter, semicolon in Rust bugs me a lot.

2 Likes

The difference is that semicolons have meaning in Rust, in contrast to other languages you have mentioned:

fn foo() -> usize { 0 }
fn bar() -> usize { 0; }

Will have behave differently (in fact, one will not compile at all).

My issue with Rust is ? operator which changes flow of the application. TBH I would prefer it to be “coalesce operator”, so instead of:

let foo: Foo = a()?.b()?.c()?;

It would work like:

let foo: Option<Foo> = a()?.b()?.c();
4 Likes

In the interest of balance, I’ve posted:

:nerd_face:

4 Likes

Remember this, the ‘semicolon’ is the sequence binary operator. Just like + is. See a + b will run a, then run b, then add them together and return the result, and a ; b will run a, then run b, then it returns b’s result (throwing away a’s). This is common in most languages that use semicolons as you need some way to ‘sequence’ operations. Elixir also has ; but it makes newlines pretend to be a ; when you aren’t in an expression body, which does introduce some syntax ambiguities in elixir (and javascript) that you end up hitting when you do enough coding in them.

So in Rust the ; is not a delimiter, its the sequence operator, and you absolutely do not need it when you don’t have a need for sequenced operations, and without it you couldn’t know how to sequence operations otherwise (remember, in Rust any whitespace, whether a space, tab, or newline are all the same thing).

? started out as the macro-by-example try!, and just like the macro it still expands to the code inline. A ‘coalesce’ operator is just map, as is the proper name of such a monad style container. (? is most similar to ‘unwrap’ of a comand but instead of throwing it returns on failure).

The thing is that doing such a coalescing wouldn’t be a replacement for ? at all as ? actually removes the monad (Option/Result for example) and allows you to change the type trivially as the chain progresses. Of course you don’t need to use ? either, it just expands to normal inline code and you can write that code (or even your own macro’s) as you wish.

Also, something like let foo: Option<Foo> = a()?.b()?.c(); is painful as you’d still have to unwrap the option/result and handle the failure case anyway, which is what ? does, hence the above ?. is not only not a replacement for ? but it doesn’t even handle the same case, it’s something entirely different and would still leave the original issue of having to deal with the failing return manually.


For me though, what I’m disliking most about rust currently is the lack of GAT’s. Some other things I’d like but are currently ‘meh’ about in comparison to how overwhelmingly important GAT’s are to me are things like GADT’s or postfix macro’s or such things.

3 Likes

My idea was to change how ? works and keep try! macro. This would IMHO give the best of both worlds.

2 Likes

Hmm, except chaining try! is excessively painful in comparison… Getting postfix macro’s would ‘mostly’ fix that though! ^.^

1 Like

That is why ?. should be there.

Old code:

try!(try!(foo.bar()).baz())

“My code”:

try!(foo.bar()?.baz())
1 Like

Or pick a different operator, let’s say : just for the sake of argument, then combine them! ^.^

foo.bar():.baz()?.morestuff()

I really don’t like reading try! at the beginning, it means I have to jump back and forth when reading to see what the final type is instead of just ‘reading down the call pipe’.

1 Like

My point that I have pointed out in the RFC discussion is that ? is:|

  • much harder to catch
  • much harder to search for without real parser

In general IMHO ?. trades writer convenience over reader convenience, and as code is more often read than written, it is not something that I like, but now I need to live with it (and I even use it from time to time).

1 Like

Hmm? Finding ? in source code has always been exceedingly obvious for me. And unlike something like your chaining version it works with chains of not the same types, whether option, result, or something custom.

Why would you not have a parser?

For stuff like project-wide search? Because that would mean that I need separate tooling for searching in each project independently. With try! I could easily do:

rg '\btry!'

With ? you can get much more false-positives.

1 Like

Isn’t that a part of every IDE?

I’m curious what false positives? Or do you mean just because it’s a more common thing in comments or so (barely)? Also I’m unsure why you’d ever grep for ?, regardless of its name, lol. ^.^;

For me the biggest problem of Rust is that it has quite a difficult learning curve.

I would feel very comfortable writing my next web application in Rust, however I would not feel comfortable teaching a team Rust on the job. It’s quite a large time and effort investment, so I can’t justify it in a commercial setting when we could get many of the benefits for low cost with another language.

3 Likes

Knowing C++, and Haskell, Rust was utterly trivial to pick-up for me, it’s really an evolution of all of those languages, but this is what contributes to its learning curve, it has the speed and power of C++ but the safety and type system similar to Haskell (with a touch of other things). That’s not a simple topic to build on, but that is also what contributes to helping someone program well, and hence why going from Rust to other languages then you will almost definitely be a better programmer there than someone who has not learned Rust.

Honestly though, I’d still call it easier than C++. Not C though, but a whole lot safer.

3 Likes

That’s a good point! If I was working with a Haskell or C++ team I would feel more comfortable for sure. In my mind the team was used to a language like JavaScript, Elixir, Ruby, Java, etc.

3 Likes

Yeah, Rust is really one of these things to which you have to allocate a serious chunk of time and energy in order to learn well. Onboarding somebody in Rust in a work setting is quite inefficient. Only people with a ton of other background can pick it up quickly.

2 Likes

What alternative do you think best fits here?

1 Like

I think the best language (or tool in general) often depends largely on the team, with the business problem coming after that.

If I need something relatively fast like Rust, but don’t feel the team will be productive with Rust, I would consider Go for most the teams I’ve worked with. It’s not as fun to write though!

2 Likes

My biggest problems with rust are:

  1. The very slow compile times
  2. The large number of transient dependencies being pulled in when you want to use a library (which in itself makes #1 worse).

The willingness to rely so much on dependencies is what make me shy away from it (perhaps I am too old for this modern e npm ecosystem style of development). I don’t think it is maintainable in the long run. For example I added actix-web = “0.7” to my Cargo.toml file. It pulls in no less than 163 dependencies. Good luck auditing all of those and keeping them up to date as your project progresses. Compare with erlang yaws which only relies on erlang stdlib which I’m pretty sure has a lot to do with its longevity.

That said, rust is nice language and it is fast and actually not too verbose (perhaps a bit too many symbols (&,&’,*,<>,{}) which makes it look more complicated than it should). I implemented a svndump reader in elixir and rust and perhaps the elixir version was slightly more pleasant to write and read but it was not that much of a difference. And the rust one was so much faster.

2 Likes

True this! Using a C++ compiler infrastructure as the backend is fantastic for compiled code speed, but it’s of no help of compiling speed, lol.

They are working on cranelift still though, basically a fast JIT for running debug code near instantly, not as fast but it makes for a fast turnaround time. Then the final Release build will be a full optimization build. :slight_smile:

It can compile dependencies in parallel so it’s not that big of an issue unless you have a really really deep tree or lots of procmacro’s (macro-by-example’s are more fine) helper libraries like syn. There’s a big push to optimize a lot of these paths and remove the noise from the ecosystem, so it is getting better here too. ^.^

1 Like