Live data from Hacker News

2017 Rust Roadmap

github.com

61–70 of 201 posts

Re: 2017 Rust Roadmap

#61
post #20
post #17

Focus on high-performance servers, async I/O, C integration is very promising. These are Go's weak points, could become a good alternative and a direct competition for Go.

Care to elaborate on Go having weak async I/O support?

The programming model exposed to the user is synchronous, which happens to be implemented on top of the asynchronous primitives the OS provides.

Re: 2017 Rust Roadmap

#62
post #32

Earlier quoted context omitted.

It's important to note that Go and C have very different design goals from Rust. Go was never designed to have zero-cost abstractions (garbage collection being the most obvious outcome of this, but there are many others), and it has a runtime. C was never designed for safety and security, memory safety or otherwise. In short, Go sacrifices performance and C sacrifices safety, while Rust's goal is to sacrifice neither…

It's also important to note that Go was designed for programmer productivity and Rust wasn't. GC is incredible productivity boost which is why no recent language (except Rust) does manual memory management. Compile times in Go are a fraction of Rust compile times, which is another productivity boost. Go gives you one good way to do concurrency, Rust believes in tyranny of choice. Without mentioning that you don't pai…

> It's also important to note that Go was designed for programmer productivity and Rust wasn't.

Rust was absolutely designed for programmer productivity. Source: I was one of the designers.

> GC is incredible productivity boost which is why no recent language (except Rust) does manual memory management.

That's true, it is a productivity boost. But it also has a cost. Rust didn't want to pay that cost, especially when the same mechanisms are useful for preventing data races. (In fact, removal of GC was something that happened as a consequence of the data race freedom features; it wasn't a design goal from the beginning.)

> Compile times in Go are a fraction of Rust compile times, which is another productivity boost.

And rustc performs much more optimization. Again, a tradeoff.

> Go gives you one good way to do concurrency, Rust believes in tyranny of choice.

That's untrue. Go has threads, channels, mutexes, condition variables, and atomics. Rust has threads, channels, mutexes, condition variables, and atomics. The only thing I can think of that Rust has that Go doesn't is, like, SIMD, and I'm sure your comment wasn't just referring to SIMD.

Re: 2017 Rust Roadmap

#63

I would also suggest taking a page out of Apple's playbook and providing some official sample apps like https://developer.apple.com/library/content/navigation/#sect... . Reading the books is one thing, but seeing the patterns actually used is another. You don't need as many as Apple, only a couple really, but make sure they are well written and straddle a couple of use cases. And like go crazy with the idioms, I want…

Personally I think Rust should take this one step further. Actually build templates into the platform itself. For example one for creating a microservice complete with routes, test cases, JSON support etc. Another for a command line application. In languages with a steeper learning curve like Rust there needs to be more of an opinionated approach to teaching users.

I'm not sure how valuable this type of thing really is. Templates tend to fall out of date, since they're not actively used, they're not actively updated to new practices. I've seen this with lots of templates in other languages.

The libraries having excellent documentation and pointing to apps that are similarly implemented tends to be better maintained, IMO.

Re: 2017 Rust Roadmap

#64
post #54

Earlier quoted context omitted.

GC for in-memory data structures, RAII and lifetimes for system resources, ML-style type and module systems. That would be very close to the ideal language IMO.

The key problem: in-memory data structures can embed ownership of system resources.

I'd take an approach inspired by Standard ML's eqtypes. In Standard ML:

(0) Some types are eqtypes (akin to Rust types that implement the Eq trait, but managed entirely by the language, you can't define custom Eq impls).

(1) If a type constructor is an eqtype, then the result of applying it to an eqtype is an eqtype, but the result of applying it to a non-eqtype is a non-eqtype. For example, “list of ints” is an eqtype, but “list of functions” isn't.

Similarly, I propose that:

(0) Some types are copytypes (akin to Rust types that implement the Copy trait, again, managed entirely by the language).

(1) If a type constructor is a copytype, the result of applying it to a copytype is a copytype, but the result of applying it to a non-copytype is a non-copytype. For example, “list of ints” is a copytype, but “list of file objects” isn't.

Subtleties:

(0) If we have first-class functions, functions must be parameterized over whether they can be called more than once (akin to the distinction between FnOnce and Fn in Rust).

(1) When a value goes out of scope, its destructor is called. For copytypes, the destructor is guaranteed to be trivial, and can be optimized away. For “base non-copytypes” (e.g., file objects), the destructor is explicitly implemented by the programmer. For “derived non-copytypes” (e.g., lists of file objects, closures that have captured file objects), the destructor is automatically generated, and it does the obvious thing (destroy all file objects in the list, or captured by the closure).

Re: 2017 Rust Roadmap

#65
post #12

Earlier quoted context omitted.

The hard part doesn't go away with unless you pull in a GC or something similar to take care of lifetime bugs. In Go you always use a GC and circumvent the explicit lifetime management syntax of Rust. Some data structures are very hard to write without something akin to a GC, so my bets are on a few opcodes trickling down into mainstream cpus making GC easier to implement in optimal time and space. I'm surprised Andr…

Is this based on your experience learning lifetimes in Rust? I very rarely find myself needing to do convoluted lifetime tricks -- most of the code I write doesn't even need explicit annotations. So I'd be curious to hear what project you may have worked on as a beginner where lifetime management because a serious obstacle.

I'm not talking about Rust lifetimes but lifetimes as a common term used in many languages. What I mean is that in Rust you're forced to explicitly deal with the lifetime aspects of variables before the compiler will generate any code. In C and C++ you're free to skip that and introduce leaks or use after free bugs, which are accepted by the compiler due to the language definitions. I didn't mean to say it's more difficult. In fact, it's less work to deal with these issues in Rust before the code gets generated rather than debugging mysterious bugs. Put differently, you're debugging your code while trying to compile it instead of debugging it after hopefully someone was able to trigger it and provide enough clues for you to identify the issue.

Re: 2017 Rust Roadmap

#66
post #15

I read through the Rust book, and the problem I was having with it and the other docs is that it was hard to map the Rust concepts with what actually runs when it is compiled. For a language that touts "uncompromising performance", it was difficult for me to find performance characteristics of the underlying abstractions and std library (for example, are algebraic data structures just tagged unions or does the compil…

> for example, are algebraic data structures just tagged unions

They're tagged unions with no implicit heap allocations. I guess we should at least document that in the reference (though we don't want to overspecify, because we do some tricks in the compiler to try to avoid leaving space for the tag if we can). But I don't think it'd be a good idea to document this straight away in the book: the goal is to make Rust easy to pick up, and adding more information than necessary when introducing enums (which a lot of folks will only see for the first time in Rust) isn't going to do people any favors.

> What about iterators?

The documentation for Iter explains this pretty well, I think: https://doc.rust-lang.org/stable/std/iter/

It even shows the exact implementation of (basically) Range, to give you an idea.

That said, it would probably be worth calling out that most iterators are guaranteed not to allocate. Note, though, that that isn't a hard-and-fast constraint that implementors of the trait have to abide by—you can make your own iterators and implement them however efficiently or inefficiently you like.

> The meme that Rust is C++ without SegFaults and or race conditions is a bit misleading since the actual guarantee is that you don't get SegFaults or Race conditions outside of Unsafe blocks, and any nontrivial project will make use of unsafe blocks.

They'll make use of unsafe blocks transitively, by using unsafe code in the standard library or well-tested crates. Think of these unsafe blocks as part of the compiler: you trust the compiler to generate correct machine code when you type "a + b", so likewise you trust the standard library to do the right thing when you say "HashMap::new()".

It is not the case that most projects should use unsafe themselves everywhere: that usually just makes life harder. The primary exception is if you're binding to C code, in which unsafe is unavoidable.

Re: 2017 Rust Roadmap

#67
post #32

Earlier quoted context omitted.

It's important to note that Go and C have very different design goals from Rust. Go was never designed to have zero-cost abstractions (garbage collection being the most obvious outcome of this, but there are many others), and it has a runtime. C was never designed for safety and security, memory safety or otherwise. In short, Go sacrifices performance and C sacrifices safety, while Rust's goal is to sacrifice neither…

It's also important to note that Go was designed for programmer productivity and Rust wasn't. GC is incredible productivity boost which is why no recent language (except Rust) does manual memory management. Compile times in Go are a fraction of Rust compile times, which is another productivity boost. Go gives you one good way to do concurrency, Rust believes in tyranny of choice. Without mentioning that you don't pai…

As a long-time C++ developer I find I can be very productive writing Rust. Many modern C++ idioms translate almost directly to out-of-the-box Rust-isms. Some (including some important ones) don't, but these are relatively easy to understand and work with.

Compile times are actually not that bad. I've seen some real doozies in my day, and plenty of hacks to overcome C++ compile times (distributed compiling, pre-compile steps to collect many dozens or more source files into a single TU, etc.). Rust is just fine. Besides, for the kinds of programs Rust is targeting being productive isn't synonymous with belting out as much code as fast as one can.

As for concurrency, I think having options is great. There is rarely a one size fits all solution for concurrency and having choice mirrors real use cases very nicely.

Furthermore I really enjoy generic programming. One of the worst parts of C is the lack of real generics. It gets tiresome writing the same array, hashtable, etc. code for each different type. Hiding it behind macros is terrible. It's one of many things that make both C++ and Rust superior to Go, in my view.

That said, I do perceive a certain "feature my preferred language offers is the most important thing ever" myopia about some aspects of the Rust community. It's similar to a certain segment of the C++ community zealously beating the drum of "performance, performance performance" to the exclusion of other important things. Rust hasn't the popularity or use in the wild for its warts to be exposed yet, but time will tell. Every language has flaws and proper (and improper) uses.

Re: 2017 Rust Roadmap

#68
post #59
post #41

Earlier quoted context omitted.

> > any nontrivial project will make use of unsafe blocks. I don't think that's actually true? Most projects make use of no unsafe outside of stdlib and a handful of crates.io crates.

stdlib has plenty of unsafe blocks inside it, as do many crates. Claiming one doesn't use unsafe blocks because none are visible in one's lib.rs or whatever doesn't mean they aren't there.

I think of libstd as basically what would be part of the compiler or runtime in other languages. In some languages (e.g. Go), things like hash maps are in the language and implemented directly with unsafe code, and nobody thinks the language is less safe because of it.

Re: 2017 Rust Roadmap

#69
post #17

Focus on high-performance servers, async I/O, C integration is very promising. These are Go's weak points, could become a good alternative and a direct competition for Go.

That async IO is hidden from you is one of the few nice things about go.

As long as you split your code into goroutines, you just treat IO as synchronous, while it's actually async underneath.

Re: 2017 Rust Roadmap

#70
post #53
post #40

Earlier quoted context omitted.

I agree with some of your points, but think this is phrased a bit harsh. FWIW, I write both Go and Rust on a regular basis. Here's where I would agree with you: - Go makes it harder for someone to write overly abstract code (a common affliction!). - Being able to occasionally do type assertions in an ergonomic way is surprisingly nice. - I wish Rust had something in the stdlib like net/http. - I like that go fmt is s…

I forgot to add - I partially agree with you about the productivity of GC. For non-performance sensitive code, GC simplifies a lot. Otherwise, I find Go much nicer to reason about than Java since it has real arrays (value types!). But I find it a mixed bag of whether the naive Go version of something that shares memory by GC is simpler than the naive Rust version of something that shares memory. Sometimes ref-countin…

> Sometimes ref-counting (Rc in Rust) is fine, although that's more expensive than GC.

To nitpick: The jury's still out on that one, because Rc in Rust isn't thread-safe reference counting. I believe that non-thread-safe reference counting is quite competitive with global, cross-thread tracing GC.

When people (rightly) talk about how much slower reference counting is than tracing GC, they're almost always talking about either thread-safe tracing GC vs. thread-safe reference counting or single-threaded tracing GC vs. single-threaded reference counting. When you compare Rc to a typical multithreaded GC'd language, you're comparing multithreaded tracing GC to single-threaded reference counting, which is a much more interesting comparison.

Post reply on HN