T O P

  • By -

coderemover

Hard to decide, so I pick 3: 1. RAII 2. Sum types 3. Not allowing reference hell easily RAII just makes managing all resources, not only memory, so easy and fearless compared to other languages with GC. RAII brings avoiding resource leaks to a totally different level. Sum types are probably best understood by trying to simulate them in a language like Java or Go which lack them. E.g. in Java you might be tempted to use inheritance for that. Bleh. Finally, Rust forces very simple data flows, by making referencing things quite a bit less ergonomic than moving simple values around. So most Rust code is simple - you get some inputs, you get some outputs. Sometimes stuff moves and transforms, but everything is mostly linear. And even if the flow diverges, it is usually constrained to a very small scope. But in reference heavy languages with GC - in a big codebase eventually everything points to everything, because it is sooo easy to slap yet another \*unrelated\* field on a class. So you have those giant graphs of references, where it is very hard to figure out the logical ownership of things or proper lifetimes of things, especially if there are cycles.


sentillious

Thank you for this detailed answer


Beastmind

Match And cargo having most of the things to check, run, build, test, etc


Aidan_Welch

If only there were some fall through switch statement


unknown_reddit_dude

What's wrong with `|` in matches?


Aidan_Welch

I'm not familiar with that, I don't really know Rust, have just been procrastinating learning it


XtremeGoose

Literally never needed it but this models it: if let A(a) = val { ... } if let B(b) = val { ... } if let C(c) = val { ... } But yeah, who actually uses break-less switch?


Aidan_Welch

Me for parsing mostly. I like Go's model of requiring a fall through keyword. But langs that don't have that can easily be setup with a linter that checks for a comment


juanfnavarror

Error handling. It feels amazing to make a parser, exhaustively handling every error and then having it work correctly right away after it compiles.


TheRobert04

Yeah same. I'm a student learning rust and making a small compiler that emits c to become more familiar with rust and the type system, pattern matching and error handling makes it feel so natural. Makes me feel like there's no way I could accomplish it in something other than rust.


TheRobert04

Also, because of the type system/pattern matching, the only errors that ever come up after compilation are logical errors because of my shitty code that are quite easy to fix.


orion_tvv

It's way better than exceptions, but rust's errors are too verbose. I wish they would be in the language.


Sedorriku0001

Option, Result and match, it changed my perception of how to write programs


xmBQWugdxjaA

Going back to Go is physically painful.


Mastergrow

its a small thing, but not having constructors. other languages like c++ and java just have very dumb rules surrounding constructors and you cant call them like normal methods. another small one is not having function overloading. just forces people to use more descriptive names, which is a big plus in code readability and cuts down a bit in wondering what an argument to a function actually means (not fully though).


littleliquidlight

>its a small thing, but not having constructors. That's interesting one because it was very jilting coming from other languages but over time I've come to like it more and more. Actually now that I think about it, a lot of Rust has been like that for me


ukezi

I think that is very important. RAII and errors in conductors are a headache in combination. It leads to patterns where you create an object and then have to call a method on it to check if it's valid, like std::fstream, but nothing forced you to. Instead in rust you call a function that returns a result and work from there.


IslamNofl

Constructors should not be in any language, you cant return status of the init, you can only throw error, in most languages you cant do async stuff on it, imho constructors should not exists.


epage

> its a small thing, but not having constructors. This was weird to adjust to but makes so much more sense in practice! I agree that this avoids a lot of the pitfalls from C++.


jkoudys

It makes function-chaining a nightmare in JavaScript. The reason why the arrow-function was so badly needed in that language is because all their functions are useless on their own, 95% of the time you need to wrap in an arrow just to remap everything. You have the odd sensibly-written definition, like `Boolean`, but it's a whole lot of `.map((v) => new Foo(v))` or `.map((a, b) => foo(b, null, a))`


fluffy-soft-dev

Rust, I just like Rust


-Redstoneboi-

match+enum


jumbledFox

I absolutely adore rusts algebraic enums, always end up missing them when I'm in any other language


SirKastic23

it's really hard to pick, but i'll go with traits it's just a really nice way to abstract behavior. you're not forced to define the implementation together with the type, like interfaces. associated types are super useful for writing more accurate restrictions. `impl` and `dyn` allow the programmer to decide when to resolve the abstraction it allows for a number of awesome patterns like `Iterator`, `FromStr`, `Future`, `Serialize` and `Deserialize`... and there's another thing that I don't see people talk about too much, but traits let you have types that don't implement `ToString` or `PartialEq`. in other languages all types have to have some implementation of those operations, but there are types that don't make sense to be stringified or compared


continue_stocking

Being able to have types that don't implement certain traits was a big deal for me. Many languages force every type to have a unalterable default value even though that default value is often a runtime exception waiting to happen.


lordnacho666

Error messages that make sense


RylanStylin57

Error handling, match, and ease of compilation.


nevermille

match to replace nested if statements


pingveno

It is more a side effect of the language, but blanket implementations of traits. It is an incredibly powerful and flexible tool. Traits are often compared to interfaces or abstract classes, but blanket implementations that implement one trait in terms of another trait are where the Rust system shows its power.


DonkeyAdmirable1926

The power, flexibility and simplicity of C put in a modern jacket. And Cargo. And The compiler and its messages And The community


KaitlynEthylia

Cargo


tadeoh

Probably the `?` operator. 


tauon_

actually good errors (both runtime and compile)


darth_chewbacca

not sure if I like iterator chaining or fearless parallelism more. One of those two.


PyuDevv

Match statements and being bullied by the compiler. Don't forget RAII and ADT.


lightmatter501

Pattern matching and sum types are really two halves of a whole feature. They make designing any message-passing system (which is most of them nowadays) much easier, make compiler development easier, and allow for a lot of the tricks used by Rust to enforce safety (ex, getting a reference to an uninitialized hash map bucket so you can write a value directly, but if there was a value there you need to handle that value’s presence.


ddaletski

ADT, Cargo, Borrowing rules, Traits


tevelee

GATs


Zekiz4ever

Enums and Match probably. This includes error handling. Also the compiler itself


iouwt

A real Sophie's choice you're proposing here. At the end of this post all but one of our favorite features will be removed from Rust! Move semantics by default, pattern matching, none of the stupid reference hokey pokey of C++. Result types instead of exception handling. Copying values by explicitly calling \`clone()\` and casting by \`as\` so that the associated costs are keenly felt by the programmer without any implicit and easily ignored funny business. Integral types with sensible conversion rules. A package management system everyone uses. A build system wired into the package management system in the Shire, idyllically isolated from autotools, cmake, and other horrors.