The problem is that instead of a general technique for solving borrow checker issues, every issue has a different specific technique. Hash map matches (like the article) require the entry API. Multiple mutable pointers into a buffer require either using a typed Vec or Vec#split_off. Cyclic data structures require an Arena or Rc<Refcell<>>. String casting issues sometimes require .map(|x| &x). Global state requires lazy_static. Nice error handling requires error_chain. When you run into problems with "Send" you need a Mutex. The list goes on...
It's like pure lazy functional programming in Haskell in that unlike other languages you can't just pick it up based on previous knowledge and patterns. You need an entirely new toolbox of pure algorithms and data structures, or in this case borrow-safe algorithms and data structures.
Don't you think C/C++ are hard to learn too? C++ has a vast surface area and I think it's unlikely that most people who use it understand much of it. When I code in C, I feel like I have to be paranoid because it's so easy to forget a path that doesn't recover allocated resources. But if I'm not paranoid, I just leak the resources and don't care about it (ever, or until many months or weeks later when the problem's discovered). So the easiness is illusory IMO. It seems to me that all of those other resource leaks are just leaking too slowly for us to discover yet.
> Each project involved tons of compiler fighting that I now know how to avoid or solve.
As frustrating as it is, it's easier than struggling with heisenbugs. Those can easily eat up days trying to reproduce issues.
> Cyclic data structures require an Arena or Rc<Refcell<>>.
Is there a way of creating a cyclic data structure that doesn't involve these types?I ask because I used the latter recently, after struggling to create lifetimes that were acceptable to the compiler. I only found it when I searched for 'cyclic data structures rust' on Google.
It would have been much nicer if the compiler could have noticed that I was trying to create a cyclic data structure and then have informed me on the different ways of doing so. Perhaps a misunderstanding on my behalf, but the error messages that I previously received felt like they were sending me on a wild goose chase.
I still don't think writing Rust code is hard, but there are definitely improvements which could be made to the compiler error messages.
It's hard because now you're in charge of building a malloc(3) implementation. Depending how important this data structure is you might need to worry about 1. about fragmentation 2. free space managment 3. adjacency and cache effects
So you've traded on hard problem for another hard problem. Not something I'd call a win.
Trees, indexes (including bitmaps), buffer allocators and even just keeping state in streaming cursors (Volcano model). Are all pain in the ass in to implement.
In fact implementing a Cursor trait for like 10 different Cursor (SrcView, Join, Project, Compute, ...) became painful because each cursor struct has it's own complex lifetime params and those lifetimes were trying to leak into the main Cursor trait.
Right now I can't do that without resolving to runtime using RefCell. In my case the plans could be entirely materialized at compile time, so not really a win.
The situation won't get better until there's some kind of abstraction over lifetimes (HKT?).
But do you learn to code in a different paradigm where you don't struggle by iterating on a compilable and runnable piece of code, but rather struggle on iterating on a non-compilable piece of code and "once it compiles, it works"?
This will get shorter as tooling gets better this year.
This was the exact same thing I kept reading back when functional programming was becoming in vogue - people were pushing for Haskell, saying that purity and laziness were amazing, type system could almost prove correctness at compile time, etc. etc. You just need to meditate deeply on category theory and draw direction graphs to become one with types and all would be revealed to you.
Hybrid functional languages got adopted in the meantime (F#/Scala/Clojure come to mind) and a lot of FP was adopted by OO languages - it wasn't pure or fancy but it solved problems in an accessible way. Most people still don't use Haskell.
I'm hoping Rust doesn't go down this path as I want a replacement for C++ badly. But saying "you need to spend a few months to get intimately acquainted with the language" is just not going to work in practice if you're hoping about breaking in to the mainstream.
So that's opposed to C++'s "It takes a few years to get acquainted to the language enough that people would want your stuff in production code"?
Nobody hires junior C++ programmers.
The parent post specific said it wanted a replacement for C++; the amount of time and effort it takes to get code right in C++ is a problem.
Rust also has a long learning curve, and its hard to quickly be productive in.
I don't think there's anything wrong with idly wishing there was some kind of middle ground where you could gradually or partially opt-in to the borrow checker with a nice modern language like rust to get started, and then gradually eliminate your GC parts or whatever.
Many game engines use a high level language with a GC like C# or (shudder) python or blueprint which are baked by C++ for the performance critical parts.
You write application logic in the scripting language, and anything that's too complex you fall back to C++ for.
If rust could somehow self host itself as a high level language like that, it would be superb.
It may stop Rust from getting widespread adoption, but I see no problem with that. C++ isn't "widely used" either by most meanings. Rust may still largely replace C++ even without magically having a less steep learning curve. (Which it, IMHO, actually has anyway.)
As someone who learned C++ first and later Rust, no it isn't. Rust's learning curve is a hell of a lot higher than C++'s.
This reminds me of when Java was trying to compete with C++, you would have all these Java people making claims that HotSpot was going to take over the world and make Java faster than C/C++. Only it never happened outside of a few specific cases because these people were "fanboys" in every sense of the word.
You like Rust, there's nothing wrong with that. You think it's better than C++, that's your belief and I'll defend your right to believe it.
But stop comparing it to C++. Just about every language over the past 20 years has users do the same thing and __C++ IS STILL KING__.
You can push rust without being unfair to C++ (NO WAY is C++ harder to learn than Rust).
Depends on what you mean. Writing good, safe, C++? Quite hard. Debatably harder than Rust, but it's debatable, not an absolute statement.
The difference is that C and C++ let you write things like doubly linked lists in day 1 of learning them, whereas Rust won't. But a good doubly linked list is tricky to get right anyway.
I learned C++ first too, and I think I have a handle on "safe" C++ practices, but it's mostly a nebulous set of conventions that shift in the particulars based on the codebase. OTOH in Rust I'm immensely productive even in random codebases.
Most of the cognitive overhead of Rust exists in C++ too, since you still need to reason about how your data is shared, just that C++ spreads the cost out over the learning curve, whereas in Rust you have to deal with it up front.
I've been programming C++ for 16 years, it's the main language at my day job, and I won't even begin to think I understand templates. But you'll see codebases that use it regularly. Const correctness? rvalue vs lvalue? ODR? SFINAE? RVO? exception safe code? template argument deduction? Then you have C++11, C++14, C++17...
Despite this, I still regularly write code that has memory, string, concurrency and bounds bugs. So does everyone else in the industry, including smarter people with more experience.
It's possible that the parts of Rust I'm not familiar with (e.g. unsafe code, macro system) turn out to be similar sinkholes, but so far, that doesn't seem to be the case.
I had the exact opposite experience, i.e. Rust allows me to not worry about memory safety and allows me to think on a much closer level of abstraction to my problem domain than C++.
Anyone who thinks this is what it means to learn a language is attacking a strawman.
OTOH, many students of programming languages learn by pushing their code (EDIT: ready or not) into production. Oh boy do they learn.
In order to just use Haskell you don't need to meditate about category theory at all.
Some things do require months -- or even years -- of studying. Like, for example, C++, Java or whatever was your first programming language. There is absolutely no getting around that.
If someone thinks they won't gain anything by going from C++ to Rust, then no effort to learn it will be worth it. Obviously the Rust devs think there is a benefit.
I think those will be trivial in that direction, harder in other - but that's not even relevant. I think if Rust aims to occupy C++ domain then it needs to be very easy to get C++ developers on board - and from what I've seen so far it's not quite the case. I'm not sure what can be done about it tho - maybe emphasize unsafe is not a dirty word but a valid approach when doing low level data structure stuff like OP ? Create an unsafe version -> refactor to safe as you're sure it does what you expect and you learn more about borrow checker instead of having to absorb it all at once.
It was, for instance, a way more natural transition than "Java and C++ to OCaml". Less educational, but as usual that trades against easy.
You have numeric pointers into arrays, they're called indices.
People who complain about how difficult rust is to learn certainly aren't learning rust as their first programming language.
Because they are required to be productive fast. A professional usually doesn't learn a new language just for the sake of it. If the language doesn't yield instant benefits then most people aren't going to bother learning it.
If a steep learning curve is expected for rust then the language will never be popular around the people who could potentially make use of it, i.e. C or C++ developers.
Many things in tech are tradeoffs. Sometimes the additional tools a language brings to the table are worth the learning curve, sometimes they aren't. There are people in the industry for which FP (or Rust, or whatever) is worth it. For you it isn't. That's life.
C++ has 30+ years of libraries, so does C. To even think you can compare Rust and C/C++ on that matter is not realistic.
Haskell suffers more from being a research playground, bad documentation for both the language and it's libraries, confronting you with many unusual concepts (type theory, monads, laziness,...) and, as a pretty old language, a lot of legacy cruft that makes a lot of things awkward (string handling is the prime example).
Rust wants to be a widely used language and while it has some aspects that are not trivial and quite often make it verbose and awkward, in reality it's not really that different from, let's say C++, apart from the borrow checker and lack of classes.
I don't think much will change about Haskell, but I have hope for Rust that it will steadily improve.
I am sure they want that. But so many responses of Rust enthusiasts to any article/blog less than flattering get very aggressive. May be Steve Jobs got away with 'You're holding it wrong' but I doubt incoming users for Rust will be this kind.
The Rust thesis is: "You should care about all these things you don't currently care about, and Rust helps (makes) you care about them." In order to enjoy Rust, you need to thoroughly buy in to that idea. Any significant deviation from that thesis defeats the very purpose of the language.
But of course most people aren't going to buy in, because it's an idea predicated on making their lives harder (in the short term) than it currently is. Rustaceans believe the long term benefits are massive, but new users cannot possibly believe that except by taking it on faith. This creates a conflict. The Rustaceans need everyone to give the language faith over an extended period of time, and anyone giving up their faith after a short trial not only drops out of the ecosystem themselves, but possibly damages the faith of others. That's a huge problem, because Rustaceans are hoping their language will one day take over a significant portion of the systems/embedded development space. That can't happen if people sour on the language so quickly. So when Rustaceans see someone slam their language with giving it an "honest try," they get upset because the damage done is palpable.
Of course, that's the wrong strategy, as it just drives people further away from the language. The right approach is to be inhumanly kind and accepting so that the frustrations are counterbalanced by support. The good news is that the Rust community at large seems to be quite nice; it's just the angry ones that show up in blog comments.
Take as an example call/cc. If I tried to explain that to a--as you put it--blub programmer, I would probably get glazed eyes in response. If I instead tried to explain it via means of a yield operator (à la Python), I would much more likely get someone who could think of use cases where they would want to use it in their own code. The limitations are not in the blub programmer, it's in the teacher for assuming that blub programmers are incapable of learning hard concepts.
It's a huge entry barrier.
I never really saw that in Haskell and I've heard people talking about it for at least 15 years. That indicates that something is missing.
You're right that there needs to be a path up to there though. The reason Scala really worked for me is that it let me make my way up to a very Haskell-like style while remaining productive every step of the way.
But saying "you need to spend a few months to get intimately acquainted with the language" is just not going to work in practice if you're hoping about breaking in to the mainstream.
You mean it's okay for everyone to struggle to work with JavaScript for years and years trying to come up with an OO system and a module system and trying to just bundle the files for the browser, but it's not okay to spend months on getting intimately acquainted with the language?
Who cares if Rust becomes mainstream, we only need the best open source code to use it (like Firefox and the other C/C++ libs that are thinking of porting over). We don't need it to be mainstream, we just need it to be possible to learn it within a reasonable timeframe (less than a year).
You're saying that like those things are a contrast, not two incarnations of the same issue. Safe-and-usable is the holy grail for exactly this reason - right now we have usable-but-unsafe. Javascript isn't a few months to get acquainted: it's a few days to get passable results and a lifetime to get good ones.
So there's a huge need for a better mainstream tool, because the alternative is letting the existing ones endure. That doesn't have to be Rust - there's plenty of space for languages that are hard, but good for key applications like safe browsers. But it has to be something - lecturing people doesn't actually reduce reliance on easy-to-learn, hard-to-secure options.
Luckily, Rust's community is much more pragmatic - but their goals are still to create something substantially different from existing languages because existing languages are not enough to guarantee what Rust guarantees.
On the other hand this defeats the goal of the language - being as safe as possible - because their domain is very sensitive to memory safety issues (browser) - promoting an ecosystem of unsafe libraries wrapped in safe facades would be against their goals.
So I guess right now, because of it's design decisions, Rust isn't simply an upgrade to C++ which I want but more of a language that took different trade-offs to solve specific problems. It remains to be seen if it's worth taking those trade-offs to be rid of C++ legacy garbage.
I have pushed this several times in the past, but there's always been a lot of resistance to the idea. Though I've always phrased it as "let's allow the safety checks to be turned off", which isn't necessarily the best phrasing...
I wonder if it'd be better to just push to make unsafe easier to use: add sugar for ptr::offset, add a -> operator, relax the restrictions on casts, and so on. When I do OpenGL programming in Rust I drop into unsafe quite regularly, and it feels just like C, except for some annoying papercuts. It'd be nice to get rid of those papercuts.
Make it easy to reason about useful kinds of partial safety. Make it easier to define properties of external systems that Rust does not control.
Have you used C++ in the real world ? Dealt with it's insane build systems, build times, obscure semantics, etc. ? Not to mention there's nothing close to a sane package manager.
There's plenty of value of just rehashing the lessons learned in last 20 years of language design to a systems language.
I don't think language developers are interested in making
such a language in general...
https://inductive.no/jai/:P
I'd argue go came from a desire to have a language that was completely uninteresting in terms of 'interesting ideas', and really just exists to Get Stuff Done.
I think more people are interested in that sort of thing than you imagine. Clearly.
Or more precisely, the designer of Jai uses C++ as "C with classes" and then goes from that, which isn't fair. He also misrepresented a few things in regards to Rust, which he doesn't even know, but comments on etc. etc.
fn foo() {
unsafe {
let x = &5; // this is still going to get borrow checked
}
}
Since it's a superset, it gives you access to new tools, that don't interact with the borrow checker, rather than "turning the borrow checker off". fn foo() {
unsafe {
let x = *const 5; // this is not going to get borrow checked
}
}First weeks in Haskell as an average joe programmer you'll spend getting your brain wrapped around lazy eval being the default.
You can't tell from the type signature alone if a pure function uses ST though, so I'd say that counts as pure :)
Besides, as a Python trainer I can make you productive in it in a few days. But it will still take a lot of time for you to be good at it. The only difference with rust is that the first "reward stimuli" comes later down the road because you need to be better at it than at Python to make use of it.
In my experience, most developers can't or won't put in this sort of investment. Which leads me to wonder what fields/niches will Rust land in?
This might change if, as other commenters have stated, it is taught as a first or second language, but that doesn't seem likely anytime soon...
First, C++ programmers in aggregate have to consider more than the choice of language for their projects. Odds are they work for somebody else, on a team, an established project, whatever. In these cases "C++ programmers need better tools" doesn't mean "toss the bath out with the water." Rust isn't necessarily a good move in established products, in other words.
Second, Rust would do better, in my opinion, to target folks who are new to systems programming and, for whatever (mostly invalid, in my opinion) reasons, are intimidated by C or C++. Rust is very powerful and in many ways I like it much better than C++. I think Rust offers a great way for these people to have a gentle introduction to the world of systems programming. I say "gentle" because a good portion of the "pain" of learning is front-loaded into getting a build, rather than back-loaded into futzing about with gdb (although that would be something these folks will miss out on--who doesn't like a good session with gdb with a satisfying bug squash at the end?). Get them while they're young, as they say.
The overhead for existing C++ teams is learning the language, and (potentially AFAIK) interfacing with C++ code that has no good C style API. But Rust seems to tackle even the latter quite well. I don't think you'll get around the learning curve for a new language.
This is interesting. Many universities teach Java, C, C++ or Python as a first language. The headache that many first year students suffer from these basic (relatively speaking) languages is readily apparent. Rust is very strict, and it requires an entirely different mindset to use. I wonder how this would fare with students who have a clean slate.
I suspect that the % of students who have difficulties won't be much different, overall. There may be a different distribution of when they run into trouble.
The interesting question is whether the group of students who have problems with other first programming languages is different from the group that have problems with Rust-as-a-first-language...
when a language is hard to learn, the compiler error
messages are probably just bad in terms of
comprehensibility and offer the user no direct solution.
I don't want to sound snarky but Rust really does have amazing error messages, and they literally do offer direct solutions/suggestions using literal examples and raw samples of your source code.It even offers the `rustc --explain EXXXX` (where XXXX is an error code) that give an in terminal deep dive + examples on why this is an error/how it is failing.
I never wrote a single line of rust
:|
Unfortunately, things aren't that simple and Rust really is different from other languages. It takes months of steady investment (and yes, frustration), but the payoffs are spectacular. I would urge the author to persevere. In the meantime, the community is very helpful and I'm sure you'll get lots of useful advice on the back of this post.