> Without the annotations, you can't look at code and know what is going on.
In Rust, type inference is only inside the function, which I think gets you the best of both worlds.
> In addition to that, you get the pain in the ass of having the compiler always complaining.
This has stopped so many dumb errors of mine. My types aren't complex enough to guarantee that my program is correct, but they're complex enough to at least know that my program makes sense.
I take this one step further: Having a language with rich-ish types and good error messages like rust means I can very often rely on the compiler to tell me how to fix my dumb mistakes. In other words I know where I can be just as if not more sloppy than in an interpreted language and actually get away with it for little effort. I spend a little time getting the parameter and return types as I want them, quickly write an implementation without thinking too much about references and lifetimes then let the compiler work out the details pretty much automatically.
My experience learning Perl and Python after C/C++ and C# was okay I really get the obsession with unit tests now.
One thing notable in C you usually don't have to type the type name twice. But C++/Java/C# you do. That's when I think about it was a really bad grammar mistake. Java and C# shouldn't have propagated it.
Mentioned above I agree with, designing good types is non trivial. I think that's part of the problem that designing good API's is non trivial. I can see programmers getting the hate on when dealing with code bases with crappy types and crappy API's.
In Rust, type inference is only inside the function, which I think gets you the best of both worlds.
> In addition to that, you get the pain in the ass of having the compiler always complaining.
This has stopped so many dumb errors of mine. My types aren't complex enough to guarantee that my program is correct, but they're complex enough to at least know that my program makes sense.