I do appreciate the rule set that Rust forces the programmer into, however I keep coming back to it felt to me that I was being asked to conform to the language. Maybe I'm looking at it all wrong. When I was also learning other languages it felt to me some of them conformed to me more than others, and therefore were easier to write logic towards. Is low level safe systems programming the main/only use case or is there a reason to use Rust in other domains?
It is true, you have to conform to Rust. Rust looks like an imperative and OO language, but it isn't fully either of these, so some of your intuition you may have from other languages won't be applicable.
• Rust requires more rigor around ownership and borrowing. You can't juggle pointers as freely as you'd in C, or reference everything everywhere like in GC languages.
• Rust doesn't have inheritance, so many design patterns common in C++ or Java need rethinking in Rust.
If you really insist on doing things exactly the C way, or exactly the OOP way, then some things may work, some can be fudged, but it's going to be awkward.
However, if you adopt Rust's style, which is mostly functional, with clearly thought out ownership, without too many cyclic dependencies, then everything nicely falls into place, and Rust becomes easy and productive.
Rust is a bit like Haskell: a very strong but also complicated type system that enables you to encode a lot of the logical restrictions into the API.
This is most notable immediately around the Result and Option types with their many modifiers (map, map_err, and_then, ...) and how strings work.
This can feel pretty awkward and cumbersome compared to other languages and that could be what you are describing.
It's not that way just for fun though:
Most languages hide the underlying complexity from you and 'punish' you at runtime if you violate invariants by eg throwing exceptions.
Rust forces you to deal with the invariants at compile time.
This makes you write safer code and prevents many errors, even "business logic" type errors if the API is right.
This is why "move fast and break things" aka prototyping is hard with Rust. (Note you can also circumvent many of these restrictions by using "unwrap()" et al a lot)
On the other hand, it gives you a high degree of confidence for writing and refactoring code: if it compiles, it probably works. (Assuming you were writing idiomatic code)
Rust is certainly not a good fit for every domain: the manual memory management is often overkill, and in very business logic heavy code like your typical CRUD apps, where most errors happen in logic that can't really be encoded in the type system, the value is limited.
This has been so true in my experience. I find that it does take longer overall to write something in Rust, but I almost never have to root out strange errors from my code. In shorter files, I almost never have to use ‘cargo run --debug’ twice.
I second that! I wrote a small service for a friend the other day. It had to read some bytes off a tcp stream in a certain format and route them onto an obscure protocol called a modbus. Given a screenshot of some sample input data from an excel spreadsheet and some other minimal information about the target destination format and address I was able to make the service without having access to a real input tcp stream or the destination hardware required for the modbus. However, to our amazement the software ran without fault the first time it was executed on the target server. Sure I struggled to compile it because I am still a beginner but that has just never happened to me before in my professional career with c#. There is always some side case I haven’t thought about no matter how many unit tests I write! Maybe I got lucky but it definitely had nothing to do with my skills with rust which are still basic.
To add a bit to what others have said, at some point, once you internalize what Rust asks of you, it no longer feels like conformance; you just write stuff in a Rust-y way, and things get a lot easier and more fluid. This is sort of true in all languages, ("you can write Java in any language"), but Rust doesn't let you get away with writing some types of code as much as other languages do.
Like many things, it's a tradeoff: is the cost of getting up to speed worth the benefits Rust gives? Like any tradeoff, some will say yes, some will say no.