Note I’m not being critical of the author here. I think it’s lovely to turn your passion into trying to help others learn.
I think it is a very good example of why "design by committee" is good. The "Rust Committee" has done a fantastic job
Thank you
They say a camel is a horse designed by a committee (https://en.wiktionary.org/wiki/a_camel_is_a_horse_designed_b...)
Yes:
* Goes twice as far as a horse
* On half the food and a quarter the water of a horse
* Carries twice as much as a horse
Yes, I like design by committee. I have been on some very good, and some very bad committees, but there is nothing like the power of a good committee
Thank you Rust!
Would rather have that than all the issues that JavaScript or any other weakly typed and dynamically typed language.
I'm trying to phrase this as delicately as I can but I am really puzzled.
If someone wrote an article about how playing the harp is difficult, just stick with it... would you also say that playing the harp is a terrible hobby?
I find it relatively simple. Much simpler than C++ (obviously). For someone who can write C++ and has some experience wth OCaml/Haskell/F#, it's not a hard language.
Before Rust I was hearing the same argument from Haskell or Scala developers trying to justify their language of choice.
I know Rust is here to stay, but I think it’s mostly because it has a viable ecosystem and quality developer tools. Its popularity is _in spite of_ many of its language features that trade that extra 1% of safety for 90% extra learning curve.
Complex is the wrong word. Baffling is a better word. Or counterintuitive, or cumbersome. If “easy enough for someone with experience in C++, OCaml, Haskell, and F#” were the same thing as “not hard” then I don’t think this debate would come up so frequently.
why
That doesn't mean you should though. Imagine how much energy is being wasted globally on bad Python code... The difference is of course that anyone can write it, and not everyone can write Rust. I'm not personally a big fan of Rust, I'd chose Zig any day of the week... but then I'd also choose C over C++, and I frankly do when I optimise Python code that falls in those last 5%. From that perspective... of someone who really has to understand how Python works under the hood and when to do what, I'd argue that Rust is a much easier langauge to learn with a lot less "design smell". I suppose Python isn't the greatest example as even those of us who love it know that it's a horrible language. But I think it has quite clearly become the language of "everyone" and even more so in the age of LLM. Since our AI friends will not write optimised Python unless you specifically tell them to use things like generators and where to use them, and since you (not you personally) won't because you've never heard about a generator before, then our AI overlords won't actually help.
The problem with articles like this is that they don't really get to the heart of the problem:
There are programs that Rust will simply not let you write.
Rust has good reasons for this. However, this is fundamentally different from practically every programming language that people have likely used before where you can write the most egregious glop and get it to compile and sometimes even kinda-sorta run. You, as a programmer, have to make peace with not being able to write certain types of programs, or Rust is not your huckleberry.
I started to learn Rust, but I was put off by the heavy restrictions the language imposes and the attitude that this is the only safe way. There's a lack of acknowledgement, at least in beginner materials, that by choosing to write safe Rust you're sacrificing many perfectly good patterns that the compiler can't understand in exchange for safety. Eventually I decided to stop because I didn't like that tradeoff (and I didn't need it for my job or anything)
I remember both MS and goog having talks about real-world safety issues in the range of 50% of cases were caused by things that safe rust doesn't allow (use after free, dangling pointers, double free, etc). The fact that even goog uses it, while also developing go (another great language with great practical applications) is telling imo.
Secondary, Mojo's lifetime does not tell the compiler when a value is safe to use but when it is safe to delete, in this way the lifetime is not scope based, references will extend the lifetime of the value they reference, but values will be destroyed immediately after their last use. In Mojo you'll never see "value does not live long enough".
Just these two design decisions defines away so many ergonomic issues.
I mean, you can't expect to learn a new language in a few days, it'll always take a bit of work. My feeling is that people complaining of the language being hard aren't putting the effort.
My experience is that Rust is a relatively small language which doesn't introduce a lot of new concepts. The syntax is quite intuitive, and the compiler super helpful. The borrower checker was the only new thing for me. I'm not an expert at all, but my experience is that after spending 2 weeks full-time reading books and experimenting, I was able to work professionally with the language without feeling too much friction.
On the other hand, after spending much more time on C++, I don't feel really comfortable with the language.
Many people will think, I have a garbage collected language, rust has nothing to teach me. Even in garbage collected languages, people create immutable types because the possibility of shared references with mutability makes things incredibly chaotic that they look for immutability as a sort panacea. However, once you have immutable types you quickly realize that you also need ergonomic ways of modifying those objects, the methods you create to do so are often more cumbersome than what would be permitted for a mutable object. You wish there was some way to express, "There is a time where this object is mutable and then it becomes immutable." Enter the borrow checker.
Once you are borrow checking... why are you garbage collecting? Well, expressing those timelines of mutability and existence is a cost because you need to understand the timeline and most people would rather not spend that energy--maybe mutability or the poor ergonomics of immutable objects wasn't so bad. So, I garbage collect because I do not want to understand the lifetimes of my objects. Not understanding the lifetimes of objects is what makes shared mutability hard. Immutability eliminates that problem without requiring me to understand. Rust can teach this lesson to you so that you make an informed choice.
Of course, you can also just listen to me and learn the same lesson but there is value for many people to experience it.
Because cloning as opposed to copying is expensive and it generates a new instance of a type. In C, you don't clone, you simply copy the struct or pointer, which will lead to a pointer to the same memory or a struct with members pointing to the same memory.
C++ on the other hand has a copy constructor, and you have to move explicitly, often generating unnecessary copies (in the sense of clone)
> Mojo's lifetime does not tell the compiler when a value is safe to use but when it is safe to delete,
What happens if you pass the variable mutably to a function?
What happens in what manner? Mojo uses ASAP memory model, values will always be destroyed at the point of its last use. Mojo dataflow analysis will track this.
In terms of safety, Mojo will enforce `alias xor mutability` - like in Rust.
> C++ on the other hand has a copy constructor, and you have to move explicitly, often generating unnecessary copies (in the sense of clone)
Mojo also has copy and move constructors, but unlike in C++ these are not synthesised by default; the type creator has to either explicitly define the constructors or add a synthesiser. In Mojo, you can have types that are not copyable and not movable, these types can only be passed by reference. You can also have types that are copyable but not movable, or movable but not copyable.
Historically, programmers drastically overestimate their ability to write perfectly safe code, so it's an enormous benefit if the compiler is able to understand whether it's actually safe.
The second part of your statement is very debatable based on what safe means in this case, and whether it's an enormous benefit for a given situation.
There's plenty of stories [0][1] about Rust getting in the way and being very innappropriate for certain tasks and goals, and those "enormous benefits" can become "enormous roadblocks" in different perspectives and use cases.
In my personal and very subjective opinion I think Rust can be very good when applied to security applications, realtime with critical safety requirements (in some embedded scenarios for example), that sort of stuff. I think it really gets in the way too much in other scenarios with demanding rules and pattern that prevent from experimenting easily and exploring solutions quickly.
[0]https://barretts.club/posts/rust-for-the-engine/ [1]https://loglog.games/blog/leaving-rust-gamedev/
Can you specify a few of these programs?
I can see where Rust might not allow you to write something the way you want to, but I fail to see how a program would not be expressible in rust...
What that means is for example, if you have high aesthetical ideals and try to write object oriented code you will hit a brick wall eventually. Why? Notnbecause Ruwt is a bad language, but because you try to write Rust like it is Java or something.
Rust is a very nice language if you respect that there are Rust-ways of doing things that and that these ways are more data oriented than you might be used to.
The strictness can be daunting for beginners, but with increasing complexity it becones an absolute godsend. Where in other languages I find errors only when they happen, most Rust code just works (provided you write it in a Rust way), because the errors will caught during compilation.
That doesn't prevent logic errors, but these can be addressed with the absolute stellar test integrations. Now Rust is not all roses, but it is certainly a language worth learning even if you never use it. The ways it mitigates certain classes of errors can be turned into good coding practises for other languages as well.
If it takes the average person 1 million hours to learn rust then the average person won't learn rust
If it takes the average person 1 hour to learn rust then the average person will learn rust.
If you were designing a language which would you pick all else being equal?
To your question, no but I wouldn't be puzzled when most people pick up a guitar. (Both are so much more intuitive than any programming language so the metaphor sets false expectations. Slick political move, but probably just turns more people off of Rust)
Rust isn't a language you should pick up if you're not ready to put in the work. Just like you shouldn't go for full blown automotive grade C coding if you just want to learn coding quickly to get a job or something.
Rust has a steep learning curve, but the harder part (as mentioned in the article) is to unlearn patterns from other programming languages if you think you're already a good programmer.
But why would you think all else is equal? You might not agree with the tradeoffs Rust makes, and it's not as if there's a perfect language for all uses, but it absolutely makes hard software easier to write.
I've had the opportunity to debug weird crazy memory corruption, as well as "wow it's hard to figure out how to design this in Rust", and having come to terms with things much like this blog post I now get more work done, with less corruption _and_ design problems.
The answer is straightforward: bugs exist. Even in formally proven software, mistakes can be made. Nothing is perfect.
Additionally, memory safety is a property that when people talk about it, they mean by default. All languages contain some amount of non-proven unsafe code in their implementation, or via features like FFI. Issues can arise when these two worlds interact. Yet, real-world usage shows that these cases are quite few compared to languages without these defaults. The exceptions are also a source of the CVEs you’re talking about.
For me, I almost never write "for loops" and "if statements" in Rust; instead I use "functional iterators" and "match expressions", which interface with the borrow checker more nicely.
For example, iterating over an array while modifying it is a common pattern in imperative languages that compiles fine but often causes hard to reason about logic errors during runtime. In Rust, such a thing would cause compile time errors. So instead you rewrite to be more functional, it compiles, and then the magic is it just works, which is a common property of functional languages like Haskell.
IMO a lot of the consternation about the cost of the learning curve is because developers haven't realized once you get past it, the benefit is your code more often is just correct and therefore you run into fewer runtime bugs. In other languages you get the code compiling faster, but then you spend a great deal of time debugging things at runtime which you didn't anticipate at compile time.
I can implement the non-IO parts of Brainfuck with safe Rust, so it is Turing Complete. That doesn't change the fact that there are useful programs not expressible in it.
Even pretending that they did, I don't know if "appreciat[ing]" Rust means that you're saying that you "understand" it. It seems like choosing a different word in the second sentence of a two sentence argument may be an subtle way of hinting that you don't know Rust, although you've read articles about Rust and made judgements about it. If this is true, then it doesn't strongly support the first statement.
Well, no; in my experience the difficulty overwhelmingly comes from thinking about the semantics. I.e.: these two clients currently share a mutable object; should they observe each others' mutations? Or: if I clone this object, will I regret not propagating the change to other clients?
I'm seeking to draw a distinction between disliking rust for the real (or perceived) difficulty of learning/using it, and disliking it on principle, because you don't like it's trade-offs, approach to achieving it aims, syntax, type system, etc. This dichotomy is meaningful irrespective of the level of experience one has with Rust, beyond a certain level (and for the record I believe I have the requisite level of knowledge of rust to have an informed opinion on it).
For example, I don't know much Haskell. It seems to me (and to many other I read online) like it would be difficult to learn (and maybe use), although I'm familiar with functional languages in general. However, based on the little I've learned about it so far, it is a language I'd absolutely love to dig much deeper into as time permits, because almost everything about it makes so much sense to me.
Here's something amazing, I started to design my ideal language, before I started learning Haskell, and almost every language construct in Haskell I learn about seems to match exactly how I'd designed my language by coincidence (even down to keywords like "where", "do" blocks, etc.)
For what it's worth, it appears this was considered for Rust at some point but the devs decided against it. As described by Steve Klabnik in 2018 [0]:
> This was called “early drop”, and we didn’t implement it because of worries about unsafe code. Yes, the compiler could tell for safe code, and it would be fine, but unsafe code cannot, by definition, be checked.
[0]: https://users.rust-lang.org/t/drop-values-as-soon-as-possibl...
Eschew flamebait. Avoid generic tangents. Omit internet tropes.