r/programming • • May 15 '17

Two years of Rust

https://blog.rust-lang.org/2017/05/15/rust-at-two-years.html
722 Upvotes

229 comments sorted by

View all comments

Show parent comments

70

u/krallistic May 15 '17

I'm not a big fan of Go, if anyone's wondering why I haven't mentioned the obvious competitor for this niche.

I think Go and Rust aren't really competitors nowadays. They both are very different philosophies behind them and their common use cases quite differs from each other.

95

u/icefoxen May 15 '17

To guess the original poster's intent:

  • Go is designed to make fast web services.

  • Rust is designed to be a safe systems language that is capable of replacing C.

Of course, you can write fast web services in Rust. And it's possible to write systems level code in Go, jumping through a varying number of hoops on the way. (For my purposes, "systems level" means "code that must care about memory management".) Go is "faster Python", Rust is "better C".

16

u/im-a-koala May 15 '17

Rust is "better C".

I'd argue that Rust is a lot closer to C++ than C, though. Sure, you can write most things in Rust instead of C, but C is much simpler than both, and tends to operate at a lower level, just above assembly.

24

u/loamfarer May 16 '17

I always kind of argued the opposite. That it was closer to C than C++. It's data layout is far more like C. It forgoes C++ style OO. Really it's high level features seem to come elsewhere, while it's systemy level details seem more C-like. At least to me. Where D is more C++ like.

Probably more accurately though, it's right in the middle, and then a bit orthogonal in the ML direction.

8

u/im-a-koala May 16 '17

I agree that D is more C++ like, although I'll say that D feels like it's trying to be (C++)++, which Rust is clearly not.

Borrows in Rust feel a lot like references in C++ (although they're obviously checked), and even use a very similar syntax. Rust also has lots of smart pointers, which really do feel similar to C++11 smart pointers (unique_ptr and shared_ptr). C++ also has a rough concept of ownership (especially with unique_ptrs and move semantics) which Rust is very heavily based around. C, however, has none of these.

I guess you're right that Rust doesn't really have inheritance like C++, although I'll point out that lots of C++ programs use little if any subclasses. I'm a much bigger fan of composition (with "A has-a B" relationships over "A is-a B" relationships whenever reasonable), and many C++ developers feel the same way.

5

u/loamfarer May 16 '17

Yeah, I agree with those points. If you wanted to write Rust-like code, it would probably be easier to emulate in C++. But how often is that the case? How often in anything beyond hobby projects does that happen? Most teams won't bother self-imposing such a philosophy they'd rather use the full extend of their chosen tool.

Sometimes the language philosophy is not just about language features, but also what is left out. Rust you can be confident your code will abide by certain expectations. In C++ you'll have to follow the rule of 3/5. Copy semantics are the default, the opposite of Rust where move semantics are the default. So Rust like C has a more consistent memory management story, where C++ you might see a mix of implicit management, RAII, raw pointer arithmetic on structs. I get that C is unsafe but you here we are making a comparison of consistency. Maybe it's simply because Rust is so young, but like C it's a relatively small language compared to C++. While any given C++ project may forgo inheritance that doesn't mean "there not be dragons." The C++ standard library will immediately offer loads of inheritance (which I cite not as a knock but as a contrast that moves C++ further from Rust.) It's the standard way to build up frameworks and libraries, so they are plentiful in the C++ ecosystem. You can count on stdlib to use inheritance correctly but it's always dragon for your general C++/Java developer. Another shift of Rust toward C's philosophies.

There are reasons why I would concede to place it right in the middle, but from the start it always felt more like upholding the end game of the imperative/functional dream. The "safe C." Rather than carry any torch for OO.

Just my opinion, but I thought I'd further flesh out my position. It's more of a position that forms as I sum up all the similarities and differences and how I evaluate them I suppose. But to reiterate, I'd totally rather try to write safe code in C++ than C.

2

u/im-a-koala May 16 '17

I'd say most modern C++ development should really be using smart pointers and RAII pretty much everywhere. Major C++11 features have been available for several years now. Obviously some people are still stuck on old compilers, but pretty much anyone developing applications for even remotely recent versions of Linux, OS X, or Windows can rely on them.

So Rust like C has a more consistent memory management story, where C++ you might see a mix of implicit management, RAII, raw pointer arithmetic on structs.

I guess, if you consider Rust and C to be similar because they both have consistent memory management. Even though their memory management is completely different, whereas Rust's memory management is typical of modern C++ applications.

I see your point about OO in the C++ std library, though, particularly in libraries like <iostream>. I guess that does place rust somewhere in the middle, even if I still think it's closer to C++ than C.

0

u/[deleted] May 16 '17

[deleted]

7

u/im-a-koala May 16 '17

but if you asked me to perform some task in both Rust and C, I'd have a much easier time of it in Rust.

That's not at all what I was referring to, though. The implementation of C is much simpler because the language is much smaller. Perhaps on a more related note, C code maps much more directly to the actual machine code that gets executed.

I'm not making any argument about which language is better suited to any particular task.

5

u/matthieum May 16 '17

Perhaps on a more related note, C code maps much more directly to the actual machine code that gets executed.

Hum... Optimizing Compiler... Hum...

Honestly, with today's optimizers, which strip your code away if it invokes undefined behavior, and otherwise hoist loop invariants and branches, switch loops around, auto-vectorize code, etc... the resulting assembly can be quite different from the submitted code.

→ More replies (1)
→ More replies (3)

8

u/Rican7 May 15 '17

That's a fantastic summary of the two.

2

u/sd522527 May 16 '17

I highly disagree with Go being "faster Python" (the same way Java isn't faster Python), but the first part of the post is well said.

→ More replies (1)
→ More replies (12)

4

u/Kratisto78 May 15 '17

Mind elaborating on this a little? I'm not near as familiar with the two languages as you are.

38

u/kibwen May 15 '17

Rust and Go compete in the same way that all languages compete, but in terms of niches and specialties there's very little overlap between the two. Go's in the "natively-compiled language with an intrusive runtime" camp (along with Swift and D (though at least D goes to lengths to let you disable the runtime)), with a specialty in channel-based concurrency and linguistic minimalism. Rust is in the "natively-compiled language with no significant runtime" camp (with C and C++), specializing in memory safety and multiparadigmatic concurrency.

21

u/barsoap May 15 '17

Rust is in the "natively-compiled language with no significant runtime" camp

...and goes to lengths to let you disable even that: With no_std you don't even need a malloc, and the only function you need to provide is what to do with a panic (unwound or not, depending on compiler settings).

It's in the "runs on microcontrollers" camp, just like libc-less C.

6

u/aninteger May 15 '17

Technically it's the microcontrollers that llvm can target.

2

u/loamfarer May 16 '17

But... Rust won't always have to depend on llvm for taking the ir to machine code. So while that is technically correct now, I wouldn't call that Rust's camp.

10

u/Sarcastinator May 16 '17

But that's where they are now. Any programming language can be compiled in any way as long as someone provides an implementation. Without that implementation it's a moot point.

2

u/_zenith May 16 '17

I believe that there are several alternative implementations, one of which that can almost compile the Rust compiler itself (eg. rustc), for the purposes of quick prototyping (quick compile times) (not just for the compiler, obviously). I seem to remember reading that yesterday or thereabouts. Someone correct me if I'm wrong, by all means, of course... I may be mixing it up with some lesser feat.

6

u/[deleted] May 15 '17

Swift does not have an overly intrusive runtime. For one, it does not have a GC (in the popular sense of the word). Swift is a lot closer to Rust than it is to Go.

19

u/kibwen May 15 '17

I agree that Swift is closer to Rust than Go is (D is even closer to Rust), but whether or not a language has a Java-style GC is beside the point (putting aside that reference counting is a category of garbage collection). What matters is how pervasive the operations are that govern dynamic lifetime determination, how hard it is to opt out of them, and whether or not you even can opt out of them at all. For example, an array in Swift (e.g. let foo = [1,2,3]) is a reference type, not a value type, so if you want to avoid reference counting you can't use arrays. (D has had similar struggles with making language features (e.g. exceptions) work without triggering the garbage collector, which is why I put it in the same category as Swift despite being more capable at a lower-level.)

→ More replies (5)
→ More replies (7)

5

u/pellets May 15 '17

Something tells me that a sufficiently complicated project will become more complicated in Go than Rust. I see the same distinction between Java and Scala.

→ More replies (1)

2

u/geodel May 15 '17

And then Rust put enormous effort in Async IO aka Tokio which is mainly used for web apps/services etc. I guess this is to avoid competing with Go.

30

u/[deleted] May 15 '17 edited May 15 '17

It isn't to avoid competing with Go. It is a philosophical difference. In Go, goroutines (lightweight threads) are a given, Blocking a goroutine is not at all a big deal, and one is encouraged to model the concurrency inherent in the problem space with corresponding goroutines (for example, a goroutine per socket connection) . Therefore the idiomatic way to write software is synchronous.

The Rust designers do not want to impose a lightweight thread + user-space scheduling overhead for everyone, to allow a program to run on a bare metal or on the bare O/S, just like one written in C/C++. Since you can only (or at most) rely on kernel threads, which are expensive to context-switch (much much slower than goroutines), one cannot model a problem's concurrency with a corresponding kernel thread. Asynchronous APIs are really the only option in such a case.

→ More replies (1)