Tour of Rust
tourofrust.com
tourofrust.com
First when I saw the splash screen, and saw it say "Press to Continue", I well first was confused for a split second on "press what?", then assumed it meant "click", so I clicked my mouse, then when that didn't work assumed it meant "a key" so I hit a random key, then when that didn't work, summoned my conscious brain and figured "well I guess it means click specifically on top of this link text".
And then once on the next page, glancing at a long list of languages without really reading the text I said "ok I speak English, guess I should click on that", only to see the same exact page refresh. "Maybe it's broken?", so I clicked again. When it didn't work the second time, again, conscious brain again -- "OK, guess there's a next link somewhere here", and scrolled to the bottom.
What kind of projects are a best fit for Rust, for those who are experienced with it? Any recommendations for projects to make Rust stick?
Thanks!
Find one of the most simple utility (probably a CLI) you have and rewrite it.
I have a lot, and find useful to turn some python stuff so is easier to ship (surely Go work here...)
That’s basically how I learned Go. The language is very simple coming from practically any imperative language, once I stopped hating on the directory structure imposed on me (Go module helped) and went through the short language tour, code basically flowed. Even got a nice productivity boost over Python when dealing with concurrency.
Rust is totally different. Want to deal with a few strings? Fight with borrow checker for an hour. Want some functionality outside the practically nonexistent standard library? Frantically try to find a library, turning up either none or a bunch without clear winner. Realizing that examples are outdated. Then fight with borrow checker for another hour. After a while I ask myself, why the hell should I subject myself to this torture when I don’t need to squeeze out every ounce of performance? Switch to Go or Python, be done in an hour.
esr had a similar experience: http://esr.ibiblio.org/?p=7294
> In practice, I found Rust painful to the point of unusability. The learning curve was far worse than I expected; it took me those four days of struggling with inadequate documentation to write 67 lines of wrapper code for the server.
> Even things that should be dirt-simple, like string concatenation, are unreasonably difficult. The language demands a huge amount of fussy, obscure ritual before you can get anything done.
> The contrast with Go is extreme. By four days in of exploring Go I had mastered most of the language, had a working program and tests, and was adding features to taste.
(Not saying Go doesn’t have pain points. Specifically for writing command line tools, the argument parsing story is garbage.)
Oh and I did end up learning Rust to a reasonable degree, one way or another.
Complaining about Rust's documentation is a bit weird because even back in 2015 there was quite a bit of good documentation, let alone 2017 and the language encourages good crate API documentation.
I also find it ironic that the author of The Cathedral and The Bazaar would say:
> The Rust community appears to have elected to use the decentralized nature of their crate system (which undeniably has some very nice technical properties) to execute a swarm attack on the design space around the language. Which is wonderful in theory but seems to be failing in practice.
There are certainly deficiencies in the language and the ecosystem, but to me they stem from immaturity, only 5 years out from 1.0, and not from any fundamental major mistake.
It always seemed to me that what happened here is what happens often with a lot of experienced people that try Rust and bounce, where they approach the endeavour as "I know how to program, this will be easy, I just have to map my already existing mental framework to the new language" and hit walls early on because Rust is different enough but they didn't anticipate it. Functional languages have similar issues, but the more "esoteric" syntax helps flip a switch in people's minds to learning mode. This happened to me back in May of 2015 and it wasn't until I picked it up a few months later that it clicked.
If it needs to run in the browser, or React native, I use TypeScript.
Else if it needs to run on the JVM I use Kotlin.
Else if performance doesn't matter and the project is small, I use Python.
Else if I can use a garbage collector, I use Go. Because why manually manage memory with the borrow checker in Rust if I can let the runtime handle it?
Else Rust. Because I don't want to mess with C++ anymore.
Sarcasm aside, choosing languages this way makes great sense. Though it can be hard if you don’t one that’s ideally suited to your problem set.
I don't know Rust, I've just read the book before and played around with it a little. So using C or C++ would have been a more natural choice - but I like having an opportunity to add another tool to my belt. Compared to learning Go it's been a slog.
Do you personally start writing Rust from the get-go or do you first write something in some scripting language and then transform it to rust once the basics work?
Eventually.
I struggle, a lot, for the first 3 months of Rust. Not each minute doing rust. I code in 2-3 other langs, but the slow was pretty obvious.
I think have worked in so many other langs (+12) actually hurt me most. I try to start with rust like all the rest: Go ahead coding, figure stuff along.
I stop doing like a idiot when I start looking at it as my FIRST lang ever: read a book, be slowly, PAY attention to what are the concepts "owned", "move", etc..
Also:
I try to learn with building a relational lang, and develop the routine to build very small rust projects of a single file. I have done dozens now, and I start to click to me, and can do a lot of stuff far faster and near python-speed (when simple and normal).
It really depends on your attitude toward type errors. I find rust great for exploration because when I change something, the compiler tells me how to fix everything up.
I also have a lot of bias here, of course.
[0] https://gist.github.com/siraben/5209bfc7165c45aec18eeae852ec...
I really would just like a $job working in it. But there's a bit of a chicken and egg problem there.
Got back a page with nothing but this:
We're Sorry...
Commure is unavailable in your location.
We’re required to comply with US sanctions laws that restrict the use of our site
in certain jurisdictions. Because of this, our services are not available in Crimea -
Region of Ukraine, Cuba, Iran, Iraq, Syria, North Korea and other US embargoed
countries.
But hold on a minute. I'm in England! Whatever happened to the special relationship? :)Yes, that works.
(FWIW, I'm southern Ontario. Currently @ Google for last 8.5 years. I have had health care dev experience before, and yes, it was terrible. No React experience, but 20 years general software dev experience at basically every part of the stack. Currently doing embedded though.)
Anything that you're using C++ or Go for.
If you proceed anyway, be sure candidates crossed over from C++ because, underneath the syntax fluff, they will need to understand resource management and performance cost of architectural choices. Finally, if Rust doesn't work out quite as well as hoped, they can pivot to mature tooling without loss of momentum.
I'd love a version of this for people who know Rust that was just Rust idioms, similarly explained. I hang out in Slack channel with a bunch of Rust programmers (because I'm bumbling my way around in Rust as well) and it feels like there's a lot of communally understood idioms that aren't super apparent from the Rust Book.
And yeah, the intermediate area is where things are worst now, for sure. It's sorely needed.
Anyway the author should do whatever they want. I’m glad folks other than me are writing docs! I haven’t managed to actually go through the Tour yet myself, this is just a riff on the observation made in my parent’s comment.
I felt the procedural programming aspect was best explained with as little strings as possible, and wanted to get that out of the way as soon as possible.
The Rust docs include an in-depth explanation of how Rust relates to traditional OOP: https://doc.rust-lang.org/book/ch17-00-oop.html
https://play.rust-lang.org/?version=nightly&mode=debug&editi...
As you can see this can be verbose, but you could have derive macros (like the Debug one I'm using here) to do this boilerplate for you.
An alternative way of dealing with OOP inheritance is by using traits, where you implement the behavioral relationships by writing new traits for the behavior you want, adding super traits for them.
https://play.rust-lang.org/?version=nightly&mode=debug&editi...
Similar to the usual rule of thumb about keeping functions small, keeping types small requires that the APIs you're using support you in that goal. You're totally right that, once you're trying to pass a CustomButton somewhere that wants a T: LayoutView, where LayoutView: View, it's already too late for that!
Some approaches I've used instead of the "all the traits from Button" approach:
* Maybe I don't need quite that much abstraction, and I can instead use concrete types in the layout tree (to run with the Button example). Maybe instead of replacing an entire Button with a CustomButton, I can just set some fields on a Button, or inject the Custom part into a "userdata"-like field of Button.
* Maybe I don't need everything about CustomButton to be stored in one place, and I can instead use a CustomButtonLayout type in the layout tree. Maybe the "rest" of the CustomButton just holds a reference or handle to connect it with CustomButtonLayout. (This is where people will hype the ECS pattern. IMO that is easy to go overboard with, but it is a good source of alternatives.)
* The two points above are basically just each other's inverse, while still assuming a LayoutView trait or similar. But sometimes that is the thing getting in the way, and I just need to redraw the API boundaries to avoid the problem. Maybe a lower-level API that shifts more work to the client isn't so bad after all, and then it can just work with rectangles. Or maybe a higher-level API can take on the responsibilities of CustomButton and avoid the need for so many traits.
To be fair, though, I do still wind up with inheritance-like patterns occasionally:
* I have used `struct Base<D: Derived> { .., derived: D }` where the methods of `trait Derived` take a reference to `derived` and some of the other contents of `Base`. This emulates virtual methods and protected fields, where `Base`-using code works in terms of `Base<dyn Derived>`.
* I have used `struct Derived { base: Base, .. }` with a `trait HasBase { fn base(&self) -> &Base; }`. This is closer to what you describe, but `Base`-using code instead works in terms of `B: HasBase` or `dyn HasBase`, and sprinkles in `.base()` to access `Base` directly, which collapses most of the annoying delegation boilerplate. (You can even hide the `.base()` calls if you replace `HasBase` with `Deref<Target = Base>`, though I prefer not to do that.)
* I would eventually like to see fields in traits (as in this RFC: https://github.com/rust-lang/rfcs/pull/1546). This would be a lot like the previous point, but a little more direct and perhaps more efficient. And also reminiscent of row polymorphism, which appeals to the language designer in me. :)
not saying it's a bad. just wish some effort were put into making a consistent syntax.
seems weird to me that whoever decided on the function keyword "fn" would write the "Option" type. they would have written "Opt". but no, it's "Option".
consistency is very underrated. and these things just look odd to me but the rust community think it's okay, so, oh well...
Meanwhile, in 2020 `Option` might be on its way to becoming a widely-accepted concept in language design, but back in 2011 it was still a radical idea that Rust was trying to smuggle over the border from functional languages, against the will of people used to languages with pervasive nullity. The language that eventually supplants Rust someday might call it `Opt` (in the same way that Rust turned C++'s `vector` into `Vec`), but back then `Option` needed all the lubrication it could get without having to get bogged down in the abbreviation bikeshedding.
I think the standard library ought to use slightly longer names since it's far less strictly bounded than the set of language keywords, so I'm fine with 'Option'. 'Vec' is a bit awkward from that POV, but then again 'Vector' would be a lot worse. 'Box' is also awkward in the same way but thinking about it, it's not easy to convey the notion "this value is behind a pointer" so you might as well use a conventional name and get it over with.
A pointer and a heap allocation are the obvious choice for implementing this, but the semantics are notably different than just being a pointer. Rust also does have pointer types which represent true pointers.
They should just have called it a List, and stopped the propagation of the erroneous belief that a variable-length sequence of things is a vector.
As for linked lists, given modern processors and cache behavior, there are very few places where you ever want to chase pointers for a 1D data structure. It seems like a shame to lose a good name to a data structure that should now be avoided most of the time.
If you do interoperate through FFI with code in C or similar, you will have to reach for numpy arrays, which are the typed, contiguous arrays of Python.
No, it doesn't. There are a handful of languages where this is true, and no reason other than language-specific practice to think that a list is implicitly a linked list. People always make this objection and it's honestly just bizarre.
boost.optional was introduced in 2003
Is that considered a bad thing in the Rust community?
How to read from stdin on Rust.
https://stackoverflow.com/questions/30186037/how-can-i-read-...
Naturally, `read_line` returns the number of bytes read, rather than... the line. If you want a function or macro that does simply return a string, the best way is to... download an external crate? Because nothing says "security" more than third-party dependencies for basic tasks.
Incidentally, use of said crates is different dependent on Rust 2015/2018. Half of the internet resources you will see are wrong. If you already understand the differences, you'll know which is which.
Oh, and if you see "type" unaware in a Rust codebase, you know the one thing it isn't... is a type. Generics are sometimes elided, sometimes not, and sometimes live in a separate namespace.
Oh, and if you test code on a static array of length < 32, and a similar array of length > 32, you will see completely different behaviour.
Oh, and no REPL. This has got to be my single favourite thing about Python - I am literally never surprised. Because any, single, line of code I'm not 100% on is tested in seconds. A browser-based substitute is just that, a very poor substitute.
Rust has good points, but some huge ergonomic difficulties for a beginner, that are nothing to do with "the core difficulty of programming" - you'll note I've not even mentioned how a reader is supposed to comprehend what a <&'a T> is. The best I can say is that it's good gatekeeping.
That decouples the concern of allocating the buffer from reading the actual line. It should be possible to write a wrapper that does "return the line" (in an owned buffer), and that might be a bit cleaner in simple cases. But the stdlib should focus on providing essential functionality first.
> Oh, and if you test code on a static array of length < 32, and a similar array of length > 32, you will see completely different behaviour.
This will most likely change after const generics get fully stabilized. The current code is already using them under the hood, but the separate behavior for size>32 is being kept for forward compatibility in case const generics need to change.
> you'll note I've not even mentioned how a reader is supposed to comprehend what a <&'a T> is.
That comes up almost exclusively when working with references that have different lifetimes. Rust tries to deduce lifetimes whenever possible so that writing them out isn't necessary most of the time, but sometimes the programmer has to resolve ambiguity. The whole system is still quite intuitive.
So put it in std lib. The point of computers is to not force humans to duplicate identical, basic tasks millions of times, and a major selling point of Rust is zero cost abstractions.
Stdlib Rust has everything necessary to write a read_line that returns a good abstraction - Result<&str, Err> - and instead provides a leaky one. I shouldn't be giving a pigs' ear about the buffer length. And come on, a language with vec.windows() in the std library is not minimal. It's just inconsistent.
You'd need to return either a String (and that would be a big mistake) or a Vec of u8. Which I'm sure you'd also be unhappy with
Is it, or not? What's the point of lifetimes if you can't manage that trivial outlives-the-creator task in literally every other language ever with them? Why would a String be a big mistake?
You STILL think Rust is easy to learn?
> Other languages aimed at ease of use will just allocate for you and give you the fully baked contents in a single fn call, but when you're writing code that 1) has to be called often enough where allocations can show up in your flame graphs or 2) the input is big enough that you can't realistically keep the entire thing in memory at once, you suddenly have to care about what the fn is doing internally. Making the default API for file interaction require you pass in your own buffer makes this explicit at the cost of some ease of use.
>>> Is it, or not?
>> It is.
> It is not.
I'm arguing that you can write that function. What Misdicorl is saying is that it would be
fn read_line_alloc(&self) -> Result<String>
and not fn read_line_alloc(&self) -> Result<&str>
because the &str would be an "use-after-free" situation, and Rust won't let you compile it. You need to allocate if you are reading from a file in order to be able to close (or seek) that file.yodelshady seems to be under the impression that this means the functionality they want (single method call that doesn't require passing in a buffer) can't be implemented. It can, it just needs to allocate, the same way that you need to explicitly allocate the buffer you pass into read_line.
> A very useful function does not mean you have to use it in the hot path or for huge inputs.
I'm also arguing against it being provided in the stdlib because Rust is big in avoiding "you're holding it wrong" kind of answers, by removing the possibility to hold it wrong. Reasonable people can disagree :)
I've also found it annoying in the past. If Rust didn't have a design goal of giving programmers full control over the behavior of their code, there are several ergonomics changes that we could make to make it much easier to use, but alas, that is not the language we have and we work with what we can make ergonomic and easy to use.
Even if it was true that Rust is big on that, such a function is not "holding it wrong", it is just a matter of convenience and development speed vs. performance.
For the vast majority of code it does not matter whether you allocate a few times or not. The timing difference is in the noise.
Let Rust be a convenient language rather than a PITA.
You can solve this in rust just like you can in every other language. By allocating memory in the function and returning the allocation. String, not &str, is what represents that behavior.
&str is kind of a rust wart that only exists because it's so damn useful to provide static text strings in a binary. Every other usage is pretty questionable and should basically be ignored/changed imo
In addition, since the String object itself cannot be mutated, a slice like s[10:20] as a &String requires storing the 10 and 20 outside the String and then doing pointer offsets when reading the data. A &str does not need to do this, because the pointer offset happens on creation. Because of this, the &str is also smaller (and this is more efficient because of caches), because it only needs to store a pointer and length (16 bytes, on typical machines), while a &String needs to store at least a pointer to the String and the start/end indices (24 bytes).
One could have various special cases to make &String “work” but it likely ends up being equivalent to &str. The key piece in mind: if one retains the &String name, it makes the language less orthogonal, with more special cases, because taking a reference to a string variable like &s to get a value of type &String behaves very differently to taking a reference to any others like &some_int (of type &i32), which will cause problems in generic code.
Perhaps its more strange/broken to special case &String that it is to have the (imo) warty &str.
That said, it's probably worthwhile to expose the functionality since people would find it useful in a lot of cases
Aka... a nice abstraction.
Not arguing it's the best way -- and I far prefer the C++ way of returning a string or a buffer -- but it's the C way.
But it really is a C thing, because that’s just “how you do it” in C.
"fn" is pervasive, and a fundamental keyword embedded into the language. A tradeoff was made in expresiveness VS frequency of use, since it gets typed so frequently that a quick shorthand is warranted. That's the reason why "return" is not "ret", because idiomatic Rust barely uses that keyword.
Option is not even part of the language itself, it's a normal enum type in the std lib imported by the prelude.
I often have a similar dicussion around "let". Many of my C++ programmer colleagues seem to think that "let" is an arbitrary name to differentiate itself for the sake of it where "auto" would suffice. But what they don't see is that let is an entirely different thing (bindings, pattern matching, etc) that would be misleading to present with "auto", let alone C/C++'s type-name-value syntax.
Not to mention that "let" came from ML. The idea that they "deviated" from C++ syntax is wrong, because they didn't take the feature from C++ at all.
I'll have to strongly disagree. I tried learning it as my first language and was blown away by the prerequisite knowledge I had to have in order to understand even the basic concepts.
Added to the fact that currently there aren't even learning resources available for people like me, makes this language mostly suitable for people already familiar with other languages.
> I'll have to strongly disagree.
You're not alone... It's the first time I hear anyone saying Rust does NOT have a steep learning curve. It's widely considered as one of the most difficult languages out there (the fact it's also one of the most loved seems to not be a coincidence: only if you actually like it do you manage to get past the initial difficulty).
Even very experienced programmers find it difficult because you just can't write code the way you're used to when not having the borrow check limitations.
I would say it has a less steep learning curve than Haskell. But definitely steeper than most languages - C, C++, Go, Python, JavaScript, etc.
However, I'm not really sure the learning curve for C++ is lower. There's a lot more to learn, and there's a good chance that you're just writing incorrect programs if you haven't gone through the effort of learning about ownership semantics anyway. Does that mean you've learned the language, or just that the compiler doesn't care?
The learning cliff is in the memory management. Rust combines no GC with no memory leaks by forcing you to prove to it that your algorithm doesn't leak anything. And you have to do this every time you want your code to compile.
There's no way in Rust to write your business logic first and plug the memory leaks later. And it's not just the compiler issue, the whole ecosystem expects you to think about the right abstraction for managing memory from step zero.
This means that when you're writing Rust as a novice or a journeyman you have to simultaneously think about the correctness of your algorithm and about its memory safety.
https://doc.rust-lang.org/book/ch15-06-reference-cycles.html
> Rust combines no GC with no memory leaks by forcing you to prove to it that your algorithm doesn't leak anything. And you have to do this every time you want your code to compile.
What it does prevent is memory unsafely: read after free, double free, buffer overflows, etc.
I say this because someone coming from a functional language might be betrayed by their instincts here: it is relatively rare for Rust users to write macros themselves, and macro-heavy Rust code would generally be regarded as peculiar/unidiomatic.
Unfortunately the language documentation isn't helpful either, looking at the docs for println! [0] doesn't explain the arguments that it takes (other than referring to format!, which is another macro [1]...) or what the return value of the macro is.
[0] https://doc.rust-lang.org/std/macro.println.html [1] https://doc.rust-lang.org/std/macro.format.html
You don't "have to" understand the `println!` implementation in order to use it. It certainly helps like it does for any other API, but it can be treated as a blackbox, and still be able to use it.
I see many tech:nerd people explain this bottom-up instead of bottom-down because they can’t imagine skipping details for later. The reality is that students are intrigued by “I’ll explain what that means later” and it builds interest.
I explain how our website works by first telling a big lie: your computer requests a webpage and we have one big computer that replied with the answer. I then explain that I just lied. I then break it down: a web page requires many elements. Each requested individually. I then explain we don’t have one big computer but a cluster behind a load balancer. I then explain the many benefits of a load balancer. Then I explain that the web cluster depends on databases and other services.
All-in-all I expose 5-6 “lies” as I break down each component.
I’ve gotten positive feedback from both non-developers, entry-level developers, and expert developers.
I’ve also seen people give a bottom up description and everyone was confused at the end.
Why do top-down descriptions work better even though they initially gloss over (lie) To the audience?
Because the high level description gives The audience a mental roadmap to follow. Then we back up and walk through that roadmap in more detail. Then we walk through again in even more detail.
The entire time the audience understands where we are going and fits each bit of new information into their mental model, expanding it as we go.
Here’s how it feels to be explained to in a bottom-up manner: imagine I spent an hour with you listing out left and right turns. At the end of the hour I tell you “and that’s how You drive from NYC fo San Francisco”. JFC, Tom, couldn’t you have started with that!?!?
Don’t be that guy.
An explanation isn’t a murder-mystery novel with a surprise ending. Start with “these butler did it” and work backwards from there.
At Bell Labs we had a saying about presentations: “first show us your conclusion slide. If we disagree, rewind to the first slide and show us your talk. You have our interest. If we agree, stop. We can all go to lunch early.”
Some topics, this can’t be helped with as much, but in most cases, starting high level and progressively peeling back layers is a lot more effective.
That’s how most education is presented as well. It’s usually only domain experts who DON’T teach that think every little detail is valuable up front.
But on the other hand it means that people are less inclined to abuse them and they're a lot more hygienic than C-style macros...
I’ve written some fairly heavy Rust macro code, and I almost never need recursion— the repetition primitives generally prove sufficient for my needs. What are you doing that needs all the recursion?
https://github.com/rust-lang/rust/search?q=macro_rules&type=
Looking at some of those and reading https://doc.rust-lang.org/rust-by-example/macros/syntax.html and https://doc.rust-lang.org/reference/macros-by-example.html can potentially be instructive.
Jon Gjengset series Crust of Rust is amazing.
You can use both. You can run them more than once, perhaps changing the source with a sed or perl script between passes.
Thanks! Looks great.
2. create a new project with "cargo new foo"
3. add the code to the SRC/too.rs file
4. run with "cargo run"
[Edit] I mean you could just install Rust, copy the samples and run them locally?
Also, we perform many, many more checks beyond the ones you've mentioned, for example https://play.rust-lang.org/?version=nightly&mode=debug&editi... :)
Edit: To expand on "don't affect the happy path": most of those extra lints, checks and suggestions will be performed only if the error condition has been met. If your code doesn't trigger a mutability error, or a missing identifier error (to take from the parent's examples) the searches for suggestions are never executed. For others like style lints, those add some time to processing, but they are linear in time, we tag things that miss a lint during parsing or other passes and then emit them later.
That's not exactly the first 'feature' I'd want Rust to get.
> A char is always 4 bytes long (allowing for efficient lookup of individual characters).
Please fix this! A 4-byte char is NOT a character but a codepoint.
[0] https://www.amazon.com/Tour-2nd-Depth-Bjarne-Stroustrup/dp/0...
Rust is extremly popular here at hackernews and at reddit. It's a brilliant language. I learned it and actually wanted to use it for some services at work, but the team chose Go.
The impression of the spread of Rust one might get following hackenews or reddit is far off. In the industry Rust is not even at 0.1%. Probably less. The amount of Java, C and C++ projects is immense. That's at least what I can tell from my almost 20 years of experience as dev.
Rust is 10 years old. It's not new. There must be reasons why it's not already ubiquitous. And it's not the lack of language features or the lack of promotion :-).
The reason is simple: The choice of the programming language itself is not that important. How else can the world be full of extremly successful projects written in PHP, Python, Ruby, Java, C#, C, C++, Go, JS, ...
I don't like to write code without algebraic types and pattern matching. I don't want to check for null. But with Java or Go I have to and to be honest: It doesn't matter. A good development process is essential for successful projects. Language and tools ergonomics, matureness and stability come second.
That's why so many large projects are still on Java 8. They get the job done. The same can be said from C++ and C. If C++ was so harmful, why did Mozilla not port all of Firefox to Rust?
Rust could be a greater success in the industry. They just have to look at Go. Go gets a lot right: Standard lib and stability. Generics don't really matter if you want to build a successful product. I want it but I don't need it. A large and stable standard lib does matter. The xml package in Go's standard lib is embarrassing slow. But you can rely on it.
Rust needs a large company as patreon. It needs a more comprehensive standard lib. It needs one async runtime in the standard lib and a http server and client, crypto, etc.
Rust didn't have any pick up in adoption (understandably) until 1.0 in May 2015, as a consequence of breakneck speed changes before then as the developers understandably wanted freedom to break things until then. Also, 1.0 wasn't a "feature complete" release, it was a "we promise not to break your current code" release. It was an MVP. I would say it took a few releases before it was useful enough without having to rely on nightly features. All this to say is that saying that it is 10 years old, when code from 6 years ago would be completely alien and not compilable today, is misleading by omission.
> It needs a more comprehensive standard lib.
Reasonable people can disagree. There's a difference between having a fat stdlib that has the same cadence as the compiler, and having a "blessed" crate ecosystem that can evolve on its own. Doing it that way can let people update either their compiler or their dependencies independently of each other (modulo minimum version bumps on libraries) and opens the door to more aggressive deprecation schedules that the stdlib can never consider.
Your points about the actual popularity of the language are very true: Rust is niche now and will likely continue to be so for a while, but I don't think it will remain niche.
This is utter fantasy.
You can have a standard library that doesn't get deprecated often, or no "standard" libraries at all.
Oh, I mean, sure, you can call it a "blessed crate ecosystem", but that's just a label. A name. You can call it Bob's Best Bits, or the Stevens Standard Set, or whatever you want, but inevitably it'll be either:
a) Difficult to change because so many other libraries depend on it, because it is the established standard.
b) Easy to change because it's not the established standard and hence nobody cares if it breaks the handful of things that depend on it.
Everyone wants option (c), where an established standard is magically easy to change. But there's no such thing. Putting libraries outside the "std" namespace doesn't help in any way.
Some crates re-export typed from their dependencies, and to use those you have to match in the right crate version. This is an anti-pattern, but it happens.
Everything else (the world of Java, C#, Go, Python, JavaScript, Swift, etc.), which is the majority of the programming done nowadays, will stay the same.
Even for parallelism this holds true. I would say it is even more pronounced there, in fact. Some high-level languages even come with simple, effective ways of doing parallelism without multithreading, which simplifies problems a lot.
Of course, they may not reach the top performance that C++ or Rust might, but that is the trade off. Performance vs. development cost.
What features of Go disqualify it as a systems programming language?
C++ is not really a low level systems language because, very broadly speaking, low level stuff doesn’t benefit as much from the extreme flexibility and abstraction capabilities of C++. It’s used more as a high-performance application programming language for large, complex stuff. Go doesn’t fit that niche because it’s just not a very powerful language.
The niche where a simple language like Go is applicable for systems stuff without being too slow or high-level is extremely small. It’s a fantastic language for working on business-logic type stuff, web backends, etc, and excels when working with less experienced developers or larger teams. It’s as easy as python et al but actually has reasonable performance. But it’s not really a systems language for serious systems stuff.
Also if you think Wasm is the future for front-end programming, it suddenly makes sense to jump all-in in Rust.
Swift is backed by Apple, but whether they are willing to invest in a Swift WASM platform is another deal. The bull case for Rust is getting capital (whether money or dev time) from Microsoft and Facebook as both these companies don't have an equivalent and have use cases for Rust.
A better question: how is it ever going to topple JS? I haven't written any other language in the last 8 years.
Also, many examples have hidden context that if you open the example in the playground, you’ll see and will make compile.
Are my privacy add-ons too strict or is the server overloaded at the moment?