Before I start, I will say that I love Rust, and more often than not find it a pleasure to work with. Pretty much all my GitHub repositories[0] are in Rust, and have contributed a reasonable amount to the Rust repository itself[1]. Despite this, I think it is important to be honest. How much these are a deal breakers depends on your perspective and the domain that you are targeting. If you are working in a space where you really need performance, control over memory layout and allocation, and value strong abstractive power and excellent maintainability properties, then I doubt you will find a better choice of language than Rust once 1.0 is released.
With that in mind, here are some of the shortcomings that you may run into, along with their counterpoints:
The short version:
- It can sometimes be hard to get it to type check, but the payoff is worth it in terms of refactorability and maintainability.
- Some type system and language features are lacking, but those will most likely be added post-1.0.
- I miss some semantics from pure FP, but these have been given up for good reasons.
- The syntax is clunky, but it's not a deal breaker, and it will be more familiar to our target audience.
The long version:
You have to do more work to get your program past the borrow checker. The error messages are pretty good and you quickly develop an intuition for it, but sometimes it's not always clear why you are running into an issue. Most often though you are actually doing something subtly wrong that needs to be re-thought. The upshot is that you end up with a rock solid program at that you can refactor freely with the confidence that the compiler will help you along if and when you mess something up. This is in contrast to C and C++ where you constantly feel like you are walking on eggshells.
We don't have as much type system goodness as Haskell, especially with regard to higher order polymorphism. CTFE is also limited. Macro importing/exporting/namespacing as pretty ugly. These will all be addressed post 1.0 though.
Functions are tupled, and currying is not natural. This can make function composition harder than in languages like Haskell and ML. There is no support for guaranteed tail call optimization. There are technical reasons why implementing these are hard though without compromising the core emphasis on systems programming[2][3]. I am thankful that the core devs have chosen to be conservative on these fronts.
The syntax is curly braced, with <> for type parameter lists. Types are declared inline in function signatures (unlike in Haskell, where they are above) which can make them long and hard to read, especially when type parameters come into play - where clauses have helped alleviate this though.
- The syntax is clunky, but it's not a deal breaker, and it will be more familiar to our target audience.
If there are any areas in which this is still true, I urge you to value "familiarity" less. As I get older and older, I realize how long software timescales can be. In 40 years, people will still be programming in Rust, and nobody will remember why the syntax started out clunky. :-)
With that in mind, here are some of the shortcomings that you may run into, along with their counterpoints:
The short version:
- It can sometimes be hard to get it to type check, but the payoff is worth it in terms of refactorability and maintainability.
- Some type system and language features are lacking, but those will most likely be added post-1.0.
- I miss some semantics from pure FP, but these have been given up for good reasons.
- The syntax is clunky, but it's not a deal breaker, and it will be more familiar to our target audience.
The long version:
You have to do more work to get your program past the borrow checker. The error messages are pretty good and you quickly develop an intuition for it, but sometimes it's not always clear why you are running into an issue. Most often though you are actually doing something subtly wrong that needs to be re-thought. The upshot is that you end up with a rock solid program at that you can refactor freely with the confidence that the compiler will help you along if and when you mess something up. This is in contrast to C and C++ where you constantly feel like you are walking on eggshells.
We don't have as much type system goodness as Haskell, especially with regard to higher order polymorphism. CTFE is also limited. Macro importing/exporting/namespacing as pretty ugly. These will all be addressed post 1.0 though.
Functions are tupled, and currying is not natural. This can make function composition harder than in languages like Haskell and ML. There is no support for guaranteed tail call optimization. There are technical reasons why implementing these are hard though without compromising the core emphasis on systems programming[2][3]. I am thankful that the core devs have chosen to be conservative on these fronts.
The syntax is curly braced, with <> for type parameter lists. Types are declared inline in function signatures (unlike in Haskell, where they are above) which can make them long and hard to read, especially when type parameters come into play - where clauses have helped alleviate this though.
[0]: https://github.com/bjz?tab=repositories
[1]: https://github.com/rust-lang/rust/graphs/contributors
[2]: http://www.reddit.com/r/rust/comments/2ejxk6/minutes_from_la...
[3]: https://mail.mozilla.org/pipermail/rust-dev/2013-April/00355...