Hacker News new | past | comments | ask | show | jobs | submit login
Tour of Rust (tourofrust.com)
329 points by richardanaya 3 months ago | hide | past | favorite | 195 comments



Maybe a bit offtopic, but two minor UX issues hit me the first 15 seconds of trying to open this; sharing in case someone who maintains this sees and hears similar minor feedback --

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.


I was caught out by the 2nd one too, I hit "English" expecting to be taken to the English version of the start of the Tour.


I'm not sure if I'm the only one that this happens to, but every couple of months I end up re-learning Rust, and because I don't really have any use of it in my day to day job (Python and Go, some C++) I end up un-learning it, and then the cycle continues.

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!


> I don't really have any use of it in my day to day job (Python and Go, some C++)

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...)


> 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.


I always found that esr post quite bizarre. He's the self-proclaimed best known software developer in the world, having written quite a bit of C over the years and yet doesn't see the need or benefit of differentiating between heap allocated strings (String) and string slices into them (&str)?

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.


The biggest beef ESR had with the language as it looked like back in 2017 was the lack of a consistent story around async programming. Obviously the Rust of 2020 is rather more developed.


This mirrors my experience with Rust. That said, I'm currently creating a shared library in Rust because it seems to be the best tool for the job.

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.


Are you saying that different languages are best suited for specific tasks? There’s not one to rule them all?

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.


Yeah, I know, shocking.

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.


Is it really that easy to write a dirty script with rust? It doesn't seem like something that's very forgiving nor allows rapidly testing concepts or prototyping.

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?


> Is it really that easy to write a dirty script with rust?

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).


Depends on what you’re doing. It can be, especially if there’s a library to give you a hand.

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.


Writing interpreters in any language is a great exercise. And in Rust you can take advantage of ADTs, traits and unit testing to implement an interpreter of your choice. Plus there's also great parser combinator libraries you can use. Here's a very simple lambda calculus interpreter I wrote some time ago.[0]

[0] https://gist.github.com/siraben/5209bfc7165c45aec18eeae852ec...


Yes, I have the same experience. I've 'learned' it many times, including from back when it was really obscure and a twinkle in Graydon's eye. I am a big supporter of what it is. But at this point in my life I'm not going to be able to dedicate a chunk of time to a fresh project of my own in it.

I really would just like a $job working in it. But there's a bit of a chicken and egg problem there.


Some companies, like the one I work at (https://developer.commure.com/), will hire people to work on a Rust codebase even if their prior experience doesn't include it but are willing to learn. I would say it's worked quite well for us so far.


I just visited your link, as I would like a Rust job.

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? :)


Oh no! Can you access https://commure.com/? We are in the health-care space building tools and services to use FHIR[1] data. I'll raise the problem internally to fix our issue with the documentation site. Sadly, we are not currently hiring people outside of the US and Canada.

[1] https://www.hl7.org/fhir/overview.html


> Can you access https://commure.com/?

Yes, that works.


I also went to look and while I didn't get this error (I guess Canada is still special!) I also didn't see a jobs page. So no Rust for me!


You're probably looking for https://commure.com/careers :)


Montreal, eh? Not hiring remote?

(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.)


Given the current situation we are all working remotely, but yes, we are not hiring "remote" engineers. Having said that, please do not hesitate to apply regardless so that we can continue talking without spamming this site :)


wonder if that's a GDPR-wall gone slightly wrong (same message here in Germany)


I've recently started using Vector for observability data in a side project, with promising results.

-- https://github.com/timberio/vector


High-throughput web APIs is a pretty good fit for a rust project. Otherwise, any data system leveraging heavy parallel computations.


I learned Rust while implementing a ray tracer. I followed the book _The Ray Tracer Challenge_, by Jamis Buck. It was fantastically fun, and was a great application for Rust!


> What kind of projects are a best fit for Rust, for those who are experienced with it?

Anything that you're using C++ or Go for.


When performance and correctness are both high priorities Rust is likely a wise choice.


...presuming, also, tooling maturity and ready availability of experienced, competent staff are not.

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.


Rust is great for rewriting 30 year old unix utilities and internet activism.


This is good, but the string handling stuff should be earlier in the tour, because Rust's strings are idiosyncratic (whole blog posts have been written about str vs. String, an issue that doesn't appear in most other languages). It'd be a nit, but handling strings is one of the most important things you usually need to know to be productive.

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.


We learned the hard way with the Rust book that this is important: one of the biggest structural changes we made between the first and second editions was re-orienting the entire book around "how can we get to Strings quickly", and for exactly the reasons you state.

And yeah, the intermediate area is where things are worst now, for sure. It's sorely needed.


I think the big difference between Tour of Rust and the Book is my example sizes were meant to be as small as possible to demonstrate one concept at a time. Most of the concepts require no strings at all to explain. Particularly through the procedural programming chapters.


Sure. The issue is, it’s something that people run into very early when they try to actually write code. They won’t go through the whole Tour before trying to do so. They certainly don’t with the book :)

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'm the author here. I can tell you about my methodology for ordering. I immediately talk about text as soon as ownership and structs are explained. In Tour of Rust, I tried to hold to a principle of not explain concepts before their dependent concepts have been mentioned. I believe it's what allowed me to keep most of the pages as simple as possible.

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.


Every time I try to learn more about Rust, I keep hitting a wall around OOP. I know Rust takes the stance that composition is better then inheritance, but I've never found the examples to be very convincing. How do rust developers deal with complex structs that contain lots of properties and features. For instance, if I need to create "CustomButton" that means I have to implement all the Traits from Button, which maybe requires Traits from LayoutView, which requires Traits from View, etc.... Additionally I need to maintain duplicate properties of those objects in my Custom Button rather then inheriting from a Button struct. It sounds like a headache to maintain.


You can do almost everything with a combination of traits (for interface inheritance), simple composition and the Deref trait (to auto-forward unimplemented functions to the contained class). The one feature you're missing compared to actual OOP inheritance is open recursion, which is a big footgun more than anything (see: the "fragile base class" problem).

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


You use composition and leverage the Deref trait to make the methods of specific fields available on the parent. This works on arbitrary levels of nesting which makes it look like OOP, but depending on what you're doing this is a good idea or not.

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...


There's a lot of detail and intricacy here (in that you could likely architect a design that didn't really rely on the sort of hierarchy you describe at all), but generally if you wanted something similar to [single] inheritance you could implement std::ops::Deref for the child types. That doesn't necessary cover things like virtual methods, but those could be implemented simply as boxed functions that child instances assign on creation.


I can't speak for all Rust developers, but I try to avoid getting into situations where I need lots of properties and features on one type to begin with.

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. :)


rust doesn't look like it has a steep learning curve. not to me at least. the discouraging thing is the "weird" syntax. i feel like rust is the result of diverging ways of looking at things.

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...


The general wisdom of language/library design is that abbreviations should be used only for very common things, and only when those abbreviations are unambiguous in context. Prehistoric Rust had a rule that all keywords could be no longer than five characters (in defiance of Javascript's `function`), but forums (including HN) endlessly complained about `ret`, hence today it's `return`. :P (I admit that I wanted to Rust to change its `fn` to `func` once Swift showed its hand, but such is life.)

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.


The thing is that 'return' is not very common either, because Rust has shorthand for returning at the end of a function :-P

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.


Why not call it Pointer or Point?


A Box is not a pointer. It is an object with regular one-owner, no copies semantics. Semantically, it just breaks the object out so that it isn’t “internal” to whatever contains it (useful for keeping individual objects small or working around the requirement that a type have a known, finite size).

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.


AFAICT, Box has exactly the same semantics as C++‘s unique_ptr.


Where it can have the same semantics, yes. But if you look at the details, not exactly. For example Box is not nullable, but a not-nullable C++ equivalent is hard to do given the rest of the language.


Good point on the nullability; yes, that is indeed different from std::unique_ptr.


In game or graphical development a Point struct/object is usually reserved for Cartesian coordinates. Pointer seems too long. C's use of "*" and "&" remain my favorite though beginners may have more difficulty understanding it, similarly to Rust's Box.


> 'Vec' is a bit awkward from that POV, but then again 'Vector' would be a lot worse

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.


`List` usually refers to a linked list or similar. Vec has the important feature that it encapsulate a contiguous array, which matters in a languages like Rust.


Python is a very popular language where the list type is implemented as an array, and named a list. Calling these things vectors (C++, Rust) is unfortunate because you eventually want real vectors for working with matrices, and the behavior is different in that context.

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.


An array of references. Plus, Python has no way to consume a contiguous array directly.

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.


> `List` usually refers to a linked list or similar.

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.


Or - since lists call to mind a very specific data structure (linked lists) - they could have just called it Sequence.


A sequence does not contain duplicates. A vector can


Mathematical sequences totally can have duplicates. E.g. to take a popular example, the Fibonacci sequence starts: 0, 1, 1, ...


> but back in 2011 it was still a radical idea

boost.optional was introduced in 2003


Why not `fun` as a pun?


Because ML and Ocaml are already putting the `fun` in function. It would look way too derivative.


> It would look way too derivative.

Is that considered a bad thing in the Rust community?


No, it is not. In fact, it is often seen as a good thing: https://steveklabnik.com/writing/the-language-strangeness-bu...


FWIW, I really like fn.


You want to see sadness, from a learning curve point of view?

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.


> Naturally, `read_line` returns the number of bytes read, rather than... the line.

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.


>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.

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.


Well actually you couldn't return an &str, because it would be dropped at the end of the read.

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


>It should be possible to write a wrapper that does "return the line"

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?


It is. The reason it is not in the stdlib is because it is a foot-gun. Quoting myself from elsewhere in this thread[1]:

> 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.

[1]: https://news.ycombinator.com/item?id=23811980


It is not. A very useful function does not mean you have to use it in the hot path or for huge inputs.


>>>>It should be possible to write a wrapper that does "return the line"

>>> 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.


I will say that I agree with almost everything you’ve said on this thread, but we did add std::fs::{read,read_to_string} for files to have this convenience. Adding something for stdin would bring that up to parity.


Somehow I missed/forgot about that addition to the stdlib. I understand why (as evidenced by the requests in this same thread), but it I'm sad it's another thing I have to look for in code reviews ^_^'


Would that work with /dev/stdin on Linux ?


I’d imagine so.


> 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

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.


Re: lifetimes question.

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


&str is hardly a 'wart'. It's basically a safe version of C++ string_view, and it (together with array slices, which &str is essentially a special case of) is a very good example of the sorts of features that are enabled by Rust's focus on memory safety and close-to-the-metal efficiency.


Those &str use cases are just as easily handled by &String. Perhaps with some extra sugar to slice at a requested boundary.


&String cannot, by itself, handle a substring because it has to point to an (immutable) whole String struct in memory. Any extra syntax or types to package up subslice boundaries would almost certainly end up as something similar to &str, just with potentially different syntax and likely slower.


I think you are incorrect. Exposing a slice of a String as an &String should have no performance impact (pointer and length just like &str). The only thing that becomes interesting is whether you can expose a mutable string slice


At the very least, retrieving data from a &String will involve two pointer lookups (one for the &, one for the internal pointer in the String) whereas plain String and &str involve just one.

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.


What issues arise by aliasing &str and &String to the same (&str) implementation? Does any code actually rely on &String pointing at the String itself rather than the bytes of the string?

Perhaps its more strange/broken to special case &String that it is to have the (imo) warty &str.


Unsafe generic code likely cares, where it is coercing a &T to a *const T and then relying on pointer stability/consistency. It will also cause difficulties with methods like ‘.capacity()’, because that info is lost with &str.


Making it return a string would be a mistake for the space rust wants to (first) play in: low level system development. Returning a String requires figuring out what encoding the string has and parsing the contents in that encoding. That's not trivial or cheap or sometimes even possible (not all byte combinations are valid in all encodings) compared to filling a vec of bytes.

That said, it's probably worthwhile to expose the functionality since people would find it useful in a lot of cases


Returning a String is not necessarily a mistake; you could check for UTF-8 validity and error out if the line is not valid UTF-8 - and if you're providing a wrapper for "simple" uses, this might even be the right call. You're right that the general case involves outputing raw bytes, of course.


I don't think anyone is saying Rust is easy to learn. They're saying the complexity is justified (mostly).


On looking at my code that does file reads, and steveklabnik's suggestion - Vec<u8> makes reasonable sense. At least that way, if you want nice encodings you've got the same problem agnostic of where the "string" came from.

Aka... a nice abstraction.


read_line returning the number of bytes read instead of the bytes is a C thing. That's just how you do things in C.

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.


As the sibling comment said it's not a C thing. It is done that way in C because you have to babysit allocations. 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. Seeing this will also serve as a teachable moment, when the dev looks at the docs trying to understand why it has such an obtuse API, hopefully coming away with this comment's explanation. This might seem to be a pedantic distinction but I've seen Java codebases where buffer reuse was mandatory in the hot path and Rust is all about removing foot guns.


I agree with you on why it’s done that way in C, and certainly it can be in other languages. No argument there.

But it really is a C thing, because that’s just “how you do it” in C.


It's how Java's InputStream and Reader work, too. In any language, requiring the caller to supply the buffer is a prerequisite for efficiency.


Not to take away from your opinion (and I appreciate what you're saying) but it does bother me a bit when people who are not too familiar with Rust express their qualms with the syntax as rhetorical questions, rather than actually asking why things are the way they are. It's not arbitrary.

"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.


> 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 don't like many of the syntax choices either (e.g. the function return type syntax borrows from, but is not consistent with ML/Haskell). However, the language and tooling is already a huge improvement over C and there is already a significant community and lots of momentum. I wouldn't let a few syntactic warts put me off what could be a major improvement in the standard of systems programming.


> rust doesn't look like it has a steep learning curve

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.


The other side of the coin is that programming, software development and software engineering are really really difficult and Rust simply exposes you to a much larger subset than most other languages in order for your code to execute. Note that those things that Rust forces you to think about exist in all these other languages, they’re just hidden, for good reason, but also for a price.


> rust doesn't look like it has a steep learning curve

> 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 have the unsubstantiated theory that experienced developers have a harder time than less experienced developers when learning Rust. You need to forget a lot of constructs that work well enough in the languages you already know because they introduce things that go counter the single owner enforcement that Rust has, whereas somebody with less experience will simultaneously accept restrictions as "just the way it is" and not seek out more performant constructs that are much harder to understand.


The parent commenter is an example of a beginner programmer who found it very hard to start with Rust as a first language. I believe he's typical because as he said, you need to know A LOT of things in Rust to get even very simple things done, unlike "easier" languages like Python and JavaScript.


Not having a steep learning curve does not imply it‘s a good first language. I‘d recommend python to get started and then switching to a staticly typed lang. Rust requires you to have quite some experience to know when to use what.


It doesn't look like that because all the examples you see are working code. Try actually writing some and you will find it is quite difficult.

I would say it has a less steep learning curve than Haskell. But definitely steeper than most languages - C, C++, Go, Python, JavaScript, etc.


Of course, it all depends on your background. For me, the only part that took getting used to was the borrow checker.

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?


I'm always extremely skeptical when I see people claim C++ is easier than Rust. Rust essentially just makes you default to good practices in modern C++ and forces you to be explicit about things like copying data, allocating on the heap, etc. If C++ feels easier, it's because you either already know it and you're comparing it to something you don't know, or it's because your C++ code is actually very different than your Rust code (lots of heap allocations and copies vs. lots of stack allocations and moves), or it's because your C++ code has a lot of bugs that you haven't encountered yet.


C++ feels easier because we have 30 years' experience with teaching it to novices as a first programming language. That counts for a lot. We still don't quite know how to do this with Rust.


Writing the application logic in Rust isn't different from doing it in any other Algol-like procedural language. You even get nice functional abstractions.

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.


Rust doesn't prevent memory leaks. I thought I'd chime in since I see this claim often around these parts. See:

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.


While Rust may not guarantee freedom from memory leaks (probably no Turing complete language can), I find it makes a much better job on resource management than many other GCed languages. I find it is much easier to leak a file descriptor in Java than in Rust.


It doesn't prevent all memory leaks, but its goal is the prevention of most memory leaks/buffer overruns and other memory management errors with zero runtime overhead.


Safe rust actually let's you leak memory if you want. It tends not happen unless you try (in my limited experience).

What it does prevent is memory unsafely: read after free, double free, buffer overflows, etc.


Unfortunately for me, they don't mention macros in this tour of rust. Even after reading the official book, I'm still not comfortable with macro and macro syntax. Do you have any recommendations?


Note that I wouldn't expect a beginner to Rust to care about writing macros at all. Macros are something that you might introduce to a project eventually in order to abstract over some project-specific boilerplate (and only as a last resort; there are usually better abstractions to reach for first).

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.


It's true that writing macros is out of scope for an intro guide, but the first "hello world" example uses the println! macro so you have to understand how to use them right from the start. They're all over the standard library. I struggled with explaining this when writing my own guide to Rust - do you dive straight into explaining macro syntax in the first chapter, or just explain how this one macro works and move on? Or don't explain it at all, which is the (sensible) choice that this tour takes.

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


> the first "hello world" example uses the println! macro so you have to understand how to use them right from the start

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.


This is the essence of teaching: planning out what to gloss over and explain later.

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.”


I second this. I see too many people start with a bottom up explanation , which causes people to sour on the topic. It’s a mountain of information up front.

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.


I think it's important to understand that println! is special (Rust forcing the ! goes a long way for that and is IMO an excellent decision, I hate "fake" macro functions in C). Although simply saying "this is a macro call, not a real function which is why it can do things a normal function call couldn't" is probably good enough for an intro.


Please file bugs when the docs aren’t helpful; this is good to know!


Thanks, I've given some thought on how to address this but haven't come to a real conclusion yet. It would be nice if there was a way to document macros with some kind of pseudo-function syntax, but then with macros you can express things which just aren't available in normal functions. println! is a good example because it basically exists to work around the fact that Rust doesn't have variadic functions (thank $diety) but then you'd have to express it with a signature that doesn't exist in the language. Or even more fundamentally, println! exists in two forms, one of which takes no arguments (and just prints a newline) and one which takes a format string and arguments. That's not easy to express in a single signature. I suppose it could all be written as prose like I've just done here.


I don't think any amount of docs could make the Rust macro syntax palatable. The problem is more fundamental, macros as they are currently implemented are a huge pain to write, even if you know what you're doing. Having to rely so much on recursion for instance adds a lot of complexity.

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...


> Having to rely so much on recursion for instance adds a lot of complexity.

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?


I'm not sure that's the full story. You need macros in Rust for feature parity with, e.g. C++ templates with their metaprogramming capabilities, and C++ is definitely not a pure functional language.


It’s worth noting that C++ templates themselves are a purely functional language, and a Turing complete one at that


Feature parity with C++ is not a goal and neither should it be.


I do not see anything in zozbot234's comment that implies that Rust should strive for feature parity with C++. Some features, however, such as being able to use integer values as generic parameters, are arguably pretty useful.


Indeed. I think that's referred to as "const generics" in rust venacular


The Little Book of Rust Macros is a pretty good, but dense, overview of how macro_rules! can be used. (Procedural macros are a completely different beast).

https://danielkeep.github.io/tlborm/book/index.html


Also, there are a lot of uses of macro_rules! in the Rust compiler and standard library repository.

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.


I recommend https://m.youtube.com/watch?v=q6paRBbLgNw

Jon Gjengset series Crust of Rust is amazing.


Depending on your preference for macros, run "info m4" or "info cpp" to read the documentation.

You can use both. You can run them more than once, perhaps changing the source with a sed or perl script between passes.


Native Rust macros are generally preferred, because they prevent a few classes of error that can happen with the purely textual macros cpp and m4 use. In particular, they prevent unpaired delimiters from appearing in the macro expansion and name collisions between the macro implementation and the callsite.


As a skeptic of Rust I really appreciate this. I was very pleased to find the ASM option in the drop-down menu specifically. Coming from C/C++ I've found it difficult to understand how and why Rust generates the code that it does. Rust appears slightly less direct in its description of programs than C++ as it's shed the hardware-driven abstraction of memory and physical layout. My comfort level with seriously considering Rust for a next project is proportional to my understanding of what it's doing under the hood.

Thanks! Looks great.


The Compiler Explorer supports Rust as well, and is very good at this kind of thing. You may want to check it out if you don't already use it for C++ stuff.


The playground is rather slow, is it possible to run this locally much like how go's tour can?


1. Install rustup

2. create a new project with "cargo new foo"

3. add the code to the SRC/too.rs file

4. run with "cargo run"


Yeah. I've been getting quite a few timeouts with compilation. I'd recommend they could just check to see if the code has been modified in the examples, and if it hasn't then just pipe the results out using JavaScript/cached results. There are a few things I'm interested in (such as seeing what printing a void function comes out as) which I can't currently run, and which don't really need anything to do with the server


From what I've heared, Go compiles much faster than Rust. But I'm only experienced in Go...

[Edit] I mean you could just install Rust, copy the samples and run them locally?


Yes, I've noticed the Rust compiler does fancy stuff like check for similarly named constants, check constants have uppercase names, do static analysis to check that I've kept my immutable variables immutable, check that a semicolon is always at the end, and so on. I've never found those necessary in Go...


Most of these are written in such a way that they don't affect the happy path and if they do their pact is negligible. Are you saying that these checks are completely unnecessary, or are you saying that you'd prefer a faster compiler over one with more checks?

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.


The bigger costs as I understand them, are that everything needs to get passed through LLVM, and that the widespread use of generics increases the amount of generated code that passes through LLVM.


Last I heard, the biggest source of compile time in rustc is emitting absolutely enormous amounts of LLVM IR and leaning on aggressive low-level LLVM optimisation passes to clean things up. There are efforts to make most of these optimisations earlier that have been landing in recent releases, but I'm not sure what the overall state of it is.


I they have started doing work on that? I can't recall what it was exactly, but there was one constant or number (I'm so good at being specific) related one that did the optimization on the rust side instead of on LLVM's side.



Those are negligible in terms of compile time.


Indeed. I suspect this is just the tip of the iceberg?


I think this tour of Scala should interest rustaceans as many discover in rust their interest for advanced type system/functional features. And Scala in this aspect represent what rust should be in the next decade! http://dcapwell.github.io/scala-tour/Partial%20Function.html


> When building apis that are given PartialFunctions, its your responsibility to make sure the given input is proper for the function.

That's not exactly the first 'feature' I'd want Rust to get.


> With so much difficulty in working with Unicode, Rust offers a way to retrieve a sequence of utf-8 bytes as a vector of characters of type char.

> 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.


Sorry, off-topic, but something interesting I just went through: in the first page, where it offers you multiple languages to choose from, one of the options is "Interlingue". I've never seen it before, I didn't realize it was a conlang. Anyway, I used my google-translate addon to select a couple sentences, while having that lang selected... and it gave a comprehensible translation... and recognized original lang as Spanish. I selected the next sentence, it gave a comprehensible English translation, but recognized original lang as Romanian! Another sentence: good output, but French! Another sentence: again, perfectly good translation offered, but input lang recognized as Corsican! Truly a bizarre experience.


Pushing this language and Go as required, responsible, NG languages is another one of the foibles of the cloud/web and it's owners. For those of us in HPC and scientific compute where is the practical reason to switch from C/Python and the unix toolset?


I'm in the web field generally. Those I've spoken to outside of that field find Rust a much faster way to develop safe and stable programs that would have otherwise been written in C. Feel free to take this with a grin of salt. I suspect the C devs who don't like Rust haven't taken the time to discuss it with me.


Is the naming inspired by Stroustrup's "A Tour of C++"? [0]

[0] https://www.amazon.com/Tour-2nd-Depth-Bjarne-Stroustrup/dp/0...


This looks very much like the Go tour: https://tour.golang.org/welcome/1


Thanks for the link. It was great to read them side by side. I had my suspicions, but I think I'm more of a Go person than a Rust person.


Off topic. Asking seriously, will there be any point learning some language other than rust in coming days? Will rust be ubiquitous in future?


It's important to understand that hackernews, reddit or stackoverflow are very small parts of the software universe. At my workplace less then 10% of the devs are hanging around at hackernews or reddit. Some don't even visit stackoverflow but just read the Java docs!

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 is 10 years old.

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.


> deprecation schedules that the stdlib can never consider.

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.


In Rust you can have multiple versions of the same crate in your project. This let's you update you your dependencies almost whenever you want, even if their transitive dependencies require different versions of the same crate. You can't have multiple versions of the stdlib (the way that things are set up today).

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.


For any other language in the past few decades, the answer to that would have been "of course there is a point in learning other languages" (since none single language has taken over). I don't see why Rust that much more special.


Rust (and others like D, Ada, Zig...) won't be ubiquitous because it is a systems programming language intended to replace C and C++. This kind of languages are specialized and more costly to develop in them.

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.


I don't think "more costly" is true across the board. I think it might be more a matter of taste, in terms of which costs you prefer. Rust is often higher-cost in terms of up front design and development time to get something working. But the resulting program might have lower costs in terms of debugging and downtime afterwards. This distinction is especially strong when the program is multithreaded.


Not really. Many other mainstream languages give you memory safety, strict type systems and overall robustness without having to deal with memory management or low-level details.

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.


I'm surprised that you put Go in the latter group and not in the same group as Rust and C/C++.

What features of Go disqualify it as a systems programming language?


It’s not that fantastic for low level systems programming due to garbage collection and the runtime. If you’re working with C et al, you’re generally doing something that requires extreme control, and Go is too high level to do that nicely - you can use it of course, but it’s just... weird.

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.


Automatic heap allocation and garbage collection are big ones. People debate this endlessly, and it's true that undeniably-systems-ish software projects like Docker and CockroachDB are written in Go. But at the end of the day there will always be some systems that cannot be written in Go because of how it manages memory, which is not the case with C, C++, or Rust.


Well thats just like how one might say numpy is written in python, so portion of it certainly is but all the heavy lifing is done by C, the same goes for Docker. Docker is "just" an cli around cgroups which is a kernel feature written in again C.


That's a good point. Maybe you could argue that most of the heavy lifting in CockroachDB is actually done by RocksDB.


It's not, not at all. We've actually gone as far as replacing RocksDB with https://github.com/cockroachdb/pebble/ by default now (and it's written in Go).


Oh very cool. What was the main motivation for moving away from RocksDB?


Go is not systems programming language because it has mandatory garbage collector.


Just an opinion. Rust will never be ubiquitous in the future. It could aim to be as ubiquitous as C++ is, but I think those systems will be split among Rust and other languages whenever they’re rewritten and someone decides C++ should be eliminated. It requires some additional upfront effort that many practical projects may not have the luxury for (people/management types think it’s ok to fight random bugs in the future). Rust may not have the rich and mature library ecosystem like certain other languages either. But learning Rust will likely help in being a better programmer.


I think yes. But than I am a Rust fanboy so take this as you wish. The way I see it is: In the future, we'll have 64-128 cores per processors (maybe in a few years) and parallel programming will be the norm rather than the exception. The second point, Rust abstractions are very powerful, and they can allow for higher-level programming that you are used to in Python/JavaScript.

Also if you think Wasm is the future for front-end programming, it suddenly makes sense to jump all-in in Rust.


Do you think Swift has a future for WASM? Rust is faster and Swift is easier, and I genuinely wonder how that particular tradeoff will shake out for web.


Are you talking about the memory management model or the syntax. For the syntax, it's a matter of getting used to. For memory management, Rust has alloc::rc, so Rust gives you Swift + more options.

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.


Seriously? Ok, well the day when it starts making web apps. The day when you can't find a job unless you know how to write Rust.

A better question: how is it ever going to topple JS? I haven't written any other language in the last 8 years.


There will be a point when you type: "./configure; make" and the system you are trying to build turns out to be partially written in Rust. At that point, it can be useful to have at least some Rust under your belt.


This is already the case if the system you’re trying to build is Firefox.


This exact thing happened to me with 389-ds.


I think much of the official "rust-by-example" would benefit from using the rust playground instead of the printed examples.


All code blocks in rust by examples can be edited and have a play button.


And most of that cannot be run on playground because of incomplete source code, missing dependency or wrong configuration.


That has to do with the contents, not the playground.

Also, many examples have hidden context that if you open the example in the playground, you’ll see and will make compile.


This site can actually be used on mobile, cool!


> Execution operation failed: Compiler execution took longer than 12000 ms

Are my privacy add-ons too strict or is the server overloaded at the moment?


Probably getting the good old HN hug right now. Might want to try later.


I got the same error too, and gave up on the playground (I posted a top level comment and then deleted it after seeing I wasn’t alone).


It times out a lot. Try reloading the page, for some reason that helps sometimes.


Did anyone else notice Interlingue in the language options? Maybe we could get a Tour of Rust written in Esperanto :)


Tour of Rust english author here, David https://github.com/Dhghomon/ our Interlingue writer was one of our most passionate translators. We'd be happy to have Esperanto.


Why does the compile debug information get printed to the standard error area?


Tour de Rust? No? OK, I'll show myself out...


Too bad mr crabs isn't the guide.


He asked for too much money




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: