By Svlad_Cjelli, history, 2 months ago,

I have been trying out Rust in contests and I'm curious about other people's impressions of the language, in comparison with C++. In particular I am interested in the possibility for building higher abstractions, and for better error detection.

C++ definitely has the potential to be error-prone, but I became much more consistent with it once I started using an LSP that shows me warnings/errors as I type. That plus avoiding global variables. Now I feel like almost all of my errors are logic-based rather than due to the unsafety of the language.

Here are some of my first impressions from using Rust to solve some contest problems.

Things I enjoyed:

• iterators, map, filter, etc. I feel like the syntax is often cleaner than C++, where I would almost always default to mutable variables instead.

• Type inference is usually good

• Lightweight tuple and array syntax

• Ranges

• "const" is default

• Automatic error tracing when compiling in debug mode

Dislikes/annoyances:

• Recursive functions. This is the big one. In C++, recursive lambdas (with a Y combinator) are very convenient and allow for things like DFS without passing in a million parameters (and without global variables).

• Index has to be usize

• Casting to and from references

• The borrow checker doesn't seem to be that useful for contest problems

I'm interested in what else the language can offer! Looking forward for Egor to weigh in.

• +81

 » 2 months ago, # |   +34 I'll write later
•  » » 2 months ago, # ^ |   +5 Thanks for the response!I like the RecursiveFunction macros, though they're a bit less convenient to use than y_combinator in C++. It seems like in general, Rust benefits a lot from having an extensive template — I am used to a pretty minimal one in C++ (standard imports, debug macro, y_combinator, and a few shortcuts to save typing).I like Rust's debug messages — so far, they have helped me with failed input parsing and array bounds. Are there any other "silly mistakes" that the compiler helps you catch?I think Rust enums are great — It's sad that a lot of other languages don't have something similar. Do you have an example of creating custom enums (with stored data) to use in solving a problem? About Option — sometimes it's a bit annoying that some library functions return options even when I know it will never be None. So I end up having to write things like v.iter().max().unwrap() and v.last().unwrap() a lot. But I guess it forces you to think about corner cases...I do really like some of the syntax that Options allow though — like while let Some(x) = q.pop_front() { ... }Oh and I just thought of another small annoyance — you can't do swap(&mut v[i0][j0], &mut v[i1][j1]) like in C++.
•  » » » 2 months ago, # ^ | ← Rev. 2 →   +8 About silly mistakes — I mostly mean random undefined behaviors you can have in C++ (index out of bounds, use after free, use a variable without initializing, dereferencing nulls, ...).The most common case for using enums — is in tasks when you need to handle several different types of queries (e.g. change element of the array and calculate the sum of elements).About unwrap() — yeah, that could be annoying. That is why I created my own functions like last_exn() and implemented them for vector/slices (via traits).Hmm, unfortunatelly forbidding swap(&mut v[i0][j0], &mut v[i1][j1]) kinda makes sense, because compiler wants to protect you from running it on i0 == i1 && j0 == j1 when swap (or some other function) potentially could work badly. Though for 1-dimentional case, you can use v.swap(i0, i1). But you can implement your own Array2D and swap function for it :)
•  » » » 2 months ago, # ^ |   0 Although unwrap() is usually kind of annoying, but sometimes things like unwrap_or() can be helpful, e.g. different behaviour depending on whether array is empty or not.
•  » » 2 months ago, # ^ |   +13 Yes, Rust has all the common data structures. Here is the equivalence:std::vector -> Vecstd::deque -> VecDequestd::set -> BTreeSetstd::map -> BTreeMapstd::unordered_set -> HashSetstd::unordered_map -> HashMapstd::priority_queue -> BinaryHeapI am not sure about performance comparisons. Rust's HashMap and HashSet use better hashing than unordered_set/map, but may be slower as a result — maybe someone with more experience can chime in.
•  » » » 2 months ago, # ^ |   +32 I tried to push something into Vec once. Got a strange message about borrowing stuff, didn't want to bother learning the language properly and dropped it until maybe next time.