| > The only big thing I can think of is the safety of compile-time type checking to ensure you won't end up with some kind of runtime error from mismatched types. Is there something I'm missing? It's this but designs in statically typed languages with more expressive type systems tend to push a lot of the logic into the type system so you can't use APIs incorrectly. This isn't exclusive to Rust but I do have a few examples: The Glium OpenGL wrapper puts a lot of effort into moving errors to compile time. The overview[1] explains a bunch of them. [1] https://github.com/glium/glium#why-should-i-use-glium-instea... The Servo project uses the type system to tie rust code into the spidermonkey garbage collector so it can't be misused[2]. [2] https://research.mozilla.org/2014/08/26/javascript-servos-on... More abstractly, one of the more unique features of Rust's type system (linear types) is the ability to be sure a reference is destroyed. This makes Rust particularly good at describing state machines that are compile-time checked. Using standard OOP terms, each state is a class and its methods are the valid transitions. You can't take an invalid transition because the method is missing. You can do this in any language, though it tends to be only done in statically typed languages and it's awkward in Python. What makes Rust unique is that calling the method will consume the instance so you can't accidentally make a transition twice. Trying to call the method again is a compile error. A concrete example of this is state_machine_future[3], which generates an asynchronous state machine using macros. [3] https://github.com/fitzgen/state_machine_future#example In a slightly different use of the type system, the Rocket framework has a concept called Request Guards that allow you to map from something in the Request to a parameter in the request handler function. The overview[4] has a simple example on the "Dynamic Params" tab that maps url pieces to a string and an int. This mapping, however, is extensible and you can map to anything. If your handler needs an AdminUser, you can have the request guard pull the user id off the request, connect to the db, retrieve the user, verify the user as an admin, and only enter the handler if all that is successful. This means you can move all the logic and error handling around this into a single place that can be reused just by putting an AdminUser parameter on a handler. I've seen this done with middleware in other frameworks but in Rocket it's on-demand per-handler. As a result, the handlers only have to implement the happy path, which keeps them more compact than I've seen in dynamic language frameworks. [4] https://rocket.rs/overview/ So the general idea is to use the type system to help you use stuff right. As with anything, it's possible to overdo it and get crazy boilerplate heavy code where you have to convert/cast all over the place and unanticipated use cases can't be done but it tends to be helpful, particularly with autocomplete. |