
Rust vs. Go - ingve
https://blog.ntpsec.org/2017/01/18/rust-vs-go.html
======
wiremine
From ESR's conclusion is this:

> For comparison, I switched from Rust to Go and, in the same amount of time I
> had spent stuggling [sic] to make even a <100 LOC partial implementation
> work, was able to write and test the entire exterior of an IRC server - all
> the socket-fu and concurrency handling - leaving only the IRC-protocol state
> machine to be done.

I don't think this is an unusual experience. I'd consider myself a journeyman
programmer with 16 years of experience and probably a dozen languages under my
belt. Learning Go was unique: after 3 days I felt productive; After 2 weeks I
sort of looked around and said "is this it?" Go gets out of your way for the
most part, and performs as advertised.

For a lot of programmers, for a lot of projects, that's exactly what you want.

I've attempted to learn Rust a few times, and it always feel like I'm moving
uphill.

Rust is awesome for a number of problem spaces, so I'm not knocking it. And Go
_isn't_ awesome in a lot of ways (vendoring, I'm looking at you). But it feels
like there are a lot of core, language-level things Rust needs to improve to
attract more non-genius developers.

~~~
tetha
A friend of mine put it into good words: Go and Rust are two big conclusions,
to big follow-ups to the C and C++ world.

Go is an easy, fast, and very parallel language. Go is exactly what google
needs, in all regards. It makes sense why Go exists, it makes sense why google
is creating a way to migrate from python2 to go. Go is easier than hard C and
Go is fast.

Rust is the safe follow-up of C, but more familiar than Haskell, Caml and
such. It's a pain to get working, it sucks to program in, it requires so much
thought, it's just a bloody fucking fuck. But once rust runs, it works and
there's a very very good chance it won't break.

And that's also the reason why we'll probably build firewalls and hardened OS
in derivatives of Haskell and Rust, and we'll build Google 2 and Facebook 2 in
Go. And in my book, that's a good thing.

~~~
tomjakubowski
> It's a pain to get working, it sucks to program in, it requires so much
> though, it's just a bloody fucking fuck

What sucks about programming in Rust? What makes it a bloody fucking fuck? I
disagree on both these points:

    
    
      * Rust enums and move semantics make writing state machines a pure joy.  Far nicer than in C++ or Go.
      * Pattern matching (both fallible + infallible) is very developer friendly.
      * Option<T> and Result<T,E> are totally brilliant.
      * It's trivial to add and version-fix a dependency on an external library with Cargo.
      * Rust's ownership and move semantics help you to write cleaner, easier to understand code.

~~~
mevile
People who say Rust is hard are probably skipping on reading the really well
written Rust book. I'm not a genius in any shape or form, but I am able to
write decent Rust apps just fine. I've written an IRC bot in Rust and am
working on a file utility now.

It took me longer than 4 days (almost two weeks) to just read the rust book
(part time), so yes you're not going to get from 0 to 100 in just four days.
If that's your benchmark, how fast you can get going, then you're right Rust
isn't for you. But nobody would expect anyone to get up to speed with C++ in
just four days.

Rust is a systems programming language with a focus on security and
performance, not a play toy for people looking to write small scripts.

~~~
geodel
> not a play toy for people looking to write small scripts.

IMO this tone or slights against Go will hardly endear Rust to people. Rust's
superiority should stands on its own. Not just you I have seen this sentiment
many times by Rust enthusiasts on reddit and elsewhere.

Go already has successful companies like Docker, CoreOS etc literally built
using Go. There are 100s of companies using Go productively. Very large
software like kubernetes, docker, etcd are written in Go and they are not toy
scripts.

~~~
erikbye
Go is a language that is used to write on top of things. Rust can, maybe, be
used to write the things Go are written on top of.

This sentiment (or slight) is the same as always said of C and C++, that they
are used to make real things (systems and infrastructure, foundations), and
the sentiment (and slight) is there because there's a lot of truth to it.

Which language was used to write our *nixes, windows, the biggest web servers
(apache, nginx, IIS), haproxy, mysql, postgresql, oracle db, etc, etc? C/C++,
of course. What else?

Docker is just a front end/abstraction layer for the features already in the
Linux kernel (written in C). You can write, what's essentially just automation
tools, like this in any language.

I don't think what you write in this post is a testament to any strength of
Go. If currently there exist a testament to its strength it must just be the
fact that it's used; adoption rate/popularity, although I have not seen the
numbers.

~~~
dullgiulio
> Docker is just a front end/abstraction layer for the features already in the
> Linux kernel (written in C).

That's actually a perfect example of "systems programming", in the true sense
of the phrase. And it is done in Go, because it can be done in Go.

------
SwellJoe
I'm not quite willing to dismiss Rust merely for being hard to learn, but
after poking around in both Go and Rust for a few weeks, I feel like I could
build a project in Go (slowly, and with a lot of googling), but I don't feel
like I could build anything in Rust without a _lot_ more learning.

Rust has the same problem as C++ (to a lesser degree; maybe it'd be more fair
to compare it to Java), in that if you're a casual coder who dips into a bunch
of different projects in a bunch of different languages without ever really
specializing, it can be overwhelming. Go is much more readily accessible;
partly because it is less ambitious, and partly due to philosophical
differences. I can read most Go code, today, having only worked through "A
Tour of Go" on the website; I can't even begin to read Rust code after similar
time/effort invested.

So, yeah, Rust really _is_ hard. It may be necessary complexity to solve the
problems they wish to solve. But, it means I'm unlikely to ever have the time
to invest to make it a part of my toolbox, unless it becomes my primary job;
whereas I'm already almost there with Go. I'll probably build something real
in Go within the next month or two. It can be something I do for fun, in my
spare time, and I can expect to get useful results.

I want to like Rust. I'm just finding it hard to get to know Rust.

~~~
beefsack
I feel this conversation will be slightly different in 2018. The Rust team set
their goals and vision for 2017[1][2] and the theme of the year is largely
"ease of use."

I'll quote some of the proposed vision statement here:

    
    
      # Rust should have a lower learning curve
      
      Rust unique features make it valuable, but also means there's a lot to learn.
      A common refrain is "the first couple of weeks are tough, but it's oh so
      worth it." How many people are bouncing off of Rust before they get through
      those first couple of weeks? How many team leads are reluctant to introduce
      Rust because of the training needed? 1 in 4 survey respondents mentioned the
      learning curve.
      
      Some potential avenues: improved docs/training materials; improved compiler
      errors; language improvements (e.g. things like non-lexical lifetimes).
      
      # Rust should have basic IDE support
      
      For many people—even whole organizations—IDEs are an essential part of the
      programming workflow. In the survey, 1 in 4 respondents mentioned requiring
      IDE support before using Rust seriously. Tools like Racer and the IntelliJ
      Rust plugin have made great progress this year, but compiler integration has
      yet to get off the ground, and there's a lot of room to do more.
      
      # Rust's community should provide mentoring at all levels
      
      The Rust community is awesome, in large part because of how welcoming it is.
      But we could do a lot more to help grow people into roles in the project,
      including pulling together important work items at all level of expertise to
      direct people to, providing mentoring, and having a clearer on-ramp to the
      various official Rust teams. Outreach and mentoring is also one of the best
      avenues for increasing diversity in the project, which, as the survey
      demonstrates, has a lot of room for improvement.
    

[1]: [https://internals.rust-lang.org/t/setting-our-vision-for-
the...](https://internals.rust-lang.org/t/setting-our-vision-for-
the-2017-cycle/3958)

[2]: [https://github.com/rust-lang/rfcs/pull/1774](https://github.com/rust-
lang/rfcs/pull/1774)

~~~
michaelchisari
_Rust 's community should provide mentoring at all levels_

This was an issue as I learned. With widely popular languages, googling a
simple question like "reverse a list javascript" or "sum an array php" comes
up with a hundred different suggestions and discussions.

With Rust, most of the discussion is very low level, often by people working
on Rust itself and usually the rare answer you find is terribly out of date.

Just having a more stable language so answers don't become obsolete is a big
step, but it will still take time for those very basic questions to get
answered.

~~~
kazagistar
Are those real example questions? Cause I stackoverflow program a fair share,
but those seem a little bit low level for any language, and if you google
those for Rust, I end up with the docs for Vec and Iterator, which contain
exactly the reverse and sum methods. And this isn't some case of "fuck you
read the entire docs", the methods contain extensive built in examples
(copypasted from their respective method docs):

    
    
       let mut v = [1, 2, 3];
       v.reverse();
       assert!(v == [3, 2, 1]);
    
       let a = [1, 2, 3];
       let sum: i32 = a.iter().sum();
       assert_eq!(sum, 6);
    

I'm not saying everything is simple, and there are hard parts of rust to
learn. But as far as solving simple problems, I haven't ever had an easier
time then with Rust.

~~~
michaelchisari
_Are those real example questions?_

No, they were just off the top of my head, not to be taken literally.

And the docs aren't organized as a tutorial. If I don't know what a method or
type does, or even that it exists, I'm not going to know to look there for
examples.

~~~
kazagistar
Ok fair enough. Those two examples though are specifically not good examples,
and its hard to improve documentation without specific examples of what is
missing.

------
mcguire
Rust and Go are not readily comparable. Rust is a systems language aimed at
the same domain as C++ and, to an extent, C. Go is more akin to Java and
Python. ESR almost admits this:

" _Latency and soft-realtime performance_

" _Again, zero-overhead abstractions and no stop-the-world GC pauses give Rust
a clear +1._

" _It is worth noting that Go came nearest disqualifying itself entirely here.
If it were not possible to lock out Go’s GC in critical regions Rust would win
by default. If NTP’s challenges tilted even a little more towards hard real
time, or its critical regions were less confined, Rust would also win by
default._ "

As an aside, if ESR couldn't get Rust's ownership model, I wonder how long it
took him to internalize how not to write memory bugs in C?

~~~
baq
i guess it was in a way easier because the C compiler doesn't call you names
if you make a subtle bug and rustc states its opinion about your work in no
uncertain terms. it's harder to get going in rust, but once it goes, it
usually doesn't stop.

~~~
bjz_
You learn to love the compiler. It becomes a symbiotic relationship, and the
cycle times for refactors and debugging are short because you get such quick
up front feedback. Your productivity certainly takes a hit initially though.

~~~
drbawb
A symbiotic relationship is an apt way to phrase it. Most of my invocations of
rustc aren't even to actually compile an executable. Typically I'm running
something akin to a cargo-check[1] to ask rustc some questions about my
codebase: What type did you infer for this binding? Are these generic bounds
precise enough? How long can I keep this reference around?

In C++ I loathe generic programming, a template instantiation error is
something I fear. Whereas in Rust I knowingly compile broken generic code all
the time, because the errors are (usually) good enough to help me fix it.

[1]: [https://github.com/rsolomo/cargo-
check](https://github.com/rsolomo/cargo-check)

------
pcwalton
The concurrency complaint is strange, as almost nothing in it is correct.

1\. Rust never "course corrected" to implement CSP, and as far as I can tell
ESR is making that up.

Rust actually implemented channels and tasks as builtins first, with no
mutexes or shared state available--those came later. At some point we saw the
opportunity to reduce the complexity of the language and move the language
closer to the metal by moving channels and threads to the library instead of
keeping them as primitives. Mutexes and reader-writer locks followed a year or
two into the language's development--in fact, they were partially implemented
on top of channels at first. In fact, the motivation was essentially "hey,
look at this neat thing I can do with borrowing: safe mutexes!", not "let's
get rid of channels".

2\. The idea that channels are going away is also untrue. I've heard a couple
of people wish that channels could be removed the standard library and moved
to the nursery since they're a fairly complex implementation, and embedded
users might want a slim libstd. But nobody has ever floated the idea of
channels just vanishing outright in favor of shared state and mutexes: it's
absurd. Moreover, the standard library is stable and must be supported going
forward, so we can't make that change even if we wanted to.

3\. Go has mutexes as well. They're right in the library in the "sync"
package. They're fairly idiomatic too: embedding a mutex in your structure as
an anonymous field so that your structure can inherit the Lock() method is
common.

4\. ESR needs to be clear about exactly _what_ defects can arise with mutexes.
If he were to enumerate them, he'd find that Rust's type system is carefully
designed to avoid them.

~~~
ajb
A very useful post. Can you answer his complaint about epoll as well (maybe
you did already, and I don't know rust will enough to identify your answer).

~~~
bvinc
I thought this comment about epoll explained it pretty well:
[https://news.ycombinator.com/item?id=13431639](https://news.ycombinator.com/item?id=13431639)

~~~
ajb
Ah, right. It does.

------
didibus
I keep going back to the Simple Made Easy talk by Rich Hickey, creator of
Clojure.

Easy vs Hard as in: \- Easy to learn \- Familiar looking \- I know most of it
already vs \- Hard to learn \- Nothing works as I'm used too \- It's all new
to me

Simple vs Complex: \- Its parts are self-contained \- The parts don't depend
on each other \- Quick to get something done once you understand it vs \-
Can't separate the parts from the whole \- Each part depends on other parts \-
Slow to get something done even if you understand it

Most programmers and businesses value Easy vs Hard, because they think about
themselves, not delivery of great quality software. If you focused on delivery
of great quality software, you'd conclude hopefully that easy vs hard doesn't
matter as much as simple vs complex.

Having said that, I think Go is easy, and for the most part, it is also pretty
simple. While Rust I'd say is hard, but also very simple. Its simple in Rust
to make correct software, but not easy. C is easy, but complex. C++ is kinda
hard, and also complex.

So both Go and Rust are great improvements. Go chose to still be easy, at the
detriment of how far it could innovate, but it still innovates. This approach
is pretty smart, because what will happen probably is that a lot of people
will move to Go, as it is not a very hard change from what they know, and then
they will move to Go + 1, and then Go + 2, and then Go + 2, and eventually
they'll end up at Rust, or something similar. Doing it that way is easier.

~~~
brandonbloom
You're missing a key element from Rich's talk: Complexity occurs when things
are complected. That is, when two separate concerns are tied together.

There's lots of this in Rust, especially in the form of premature
specialization. If you define a struct or a method in Rust, you might be
forced to make some decisions about lifetime, static vs dynamic dispatch,
memory representation, mutability, etc.

These things are tied together deeply in order to create a tractable space in
which the type solver may operate. Granted, this may also create a tractable
space in which for you to think about these same issues, but that doesn't mean
its any less complected/complex.

~~~
kibwen
And yet that's inherent complexity, not accidental complexity. The way that
other languages simplify this is by hiding the complexity behind a garbage
collector, which Rust's domain can't tolerate.

~~~
brandonbloom
I don't necessarily disagree.

Although in the context of the simple vs easy notion, I suggest you grep this
page for "inherent complexity":

[https://github.com/matthiasn/talk-
transcripts/blob/master/Hi...](https://github.com/matthiasn/talk-
transcripts/blob/master/Hickey_Rich/SimpleMadeEasy.md)

He talks about the inherent complexity in resource contention.

I will point out one choice quote:

"It's making things complex because that's a decision that needs to be made by
someone who has better information."

Rust addresses this by forcing you to highly parameterize code statically,
which is probably the least bad solution we have right now for this sort of
stuff in a low-level language.

~~~
didibus
I know Rust is complected somewhat, that's why I specified that it's simple to
write correct programs in Rust. So in that perspective, it's very simple at
tackling such a complex problem. You'll find doing so is even more complected
in C.

I'd agree that to me that's just inherent complexity. Let me explain.

Imagine the safest language ever, literally, by design, it prevents all bugs,
except for functional ones.

Now implementing anything to the extent that there's 0% bugs is inherently
complex. It might be so complex that possibly no program ever written even
achieves this, in any language.

That hypothetical language would not be able to make that complexity
disappear, because it's part of the problem space, and not the specific design
of the language.

In most languages, we avoid this complexity by ignoring it. We allow buggy
software. We generally say, as long as the bugs that exist either don't occur
in practice, or don't impact users that much, it's good enough.

But, let's go back to Rich's talk. Why was he talking about Simple vs Complex?
Because complex code leads to bugs. If your language's complexity leads to bug
free software, the argument would change. In this case, just work harder to
understand the complexity and get it done. You're then guaranteed safety.

Rust is by no means this language, but it's the closest we have currently in
that space. Because of that goal, it's tackling quite a lot of complexity.
Maybe some of it is accidental, and Rust2 could improve on that.

Having said this, sometimes it's fine to allow bugs, if it allows
productivity. Use Clojure in those cases :p

------
Ericson2314
> Learning curve

No pain, no gain, but sure.

> Translation distance

62K lines sounds like typical C with no code reuse to speak of, A clean-slate
rewrite I'd hope would be much smaller, though admittedly talking about
corrode and c2go speaks of the other direction.

> Concurrency

No mention of Rust being data-race-free and Go not; unacceptably lax.

> > While I give the Rust designers credit for course-correcting by including
> CSP, Go got this right the first time and their result is better integrated
> into the core language.

Wat. Rust was originally all about CSP too, but they went away from that
because there was no need to stay. You can still do all the channel stuff you
want but there's little benefit force that idiom. Go's special support for
this is like....special-cased generics right?

> epoll

Mio? (sure future-rs is not yet ripe, but mio alone is last I checked.)
Overall, ESR seems sprinkle in lot of hatred of dependencies (bloated standard
libraries are _such_ a crutch around not having a good ecosystem), which I
personally find laughable as the brightest future of FOSS is large-scale code
and abstraction reuse as Haskell, Rust, and the like, are just making
mainstream.

~~~
tom_mellior
> 62K lines sounds like typical C with no code reuse to speak of, A clean-
> slate rewrite I'd hope would be much smaller

Um... you can derive the amount of code reuse in a project given no other
information than the number of lines of code?

~~~
Ericson2314
I mean code reused from upstream libraries. An internal abstract should either
be moved out, or probably isn't that interesting anyways.

If your abstraction has a real-world vs purely mathematical / programmatic
purpose, it probably sucks.

Functor > UserLoginFactoryBean.

------
tptacek
This is confusing. By far the most words of any concern in this piece are
dedicated to a root concern that Rust doesn't have a select/poll abstraction,
and that idiomatic network code simply allocates a task per socket. But that's
true of Golang as well; not just true but _distinctively_ true, one of the
first things you notice writing Go programs.

~~~
azernik
Au contraire: Go has a built-in 'select' keyword that lets you wait on a set
of arbitrary (blocking) channel operations. Start up blocking I/O in
goroutines, and select on channels that give you the results.

~~~
Groxx
A goroutine _is_ a "task" though. And typically you spin up a goroutine for
your select, and hang your current goroutine on its completion.

Seems pretty similar to me.

~~~
azernik
For networking, it's using epoll() under the scenes; depends on what exact
non-blocking operation you're using, though.

See this very very old HN thread:

[https://news.ycombinator.com/item?id=3565703](https://news.ycombinator.com/item?id=3565703)

(Hopefully the standard library has improved since then.)

------
hannibalhorn
It's worth noting that the author is Eric S Raymond, who we all know of...

I'd definitely agree that at this point Go is better for network services, and
the learning curve / documentation / infrastructure of Rust is a bit
scattered. I believe that as Rust matures it'll be better for the non-server
stuff (no GC, etc.) and eventually become competitive with Go in this space.
I'm quite fond of both languages, though!

~~~
escape_goat
Yes, he is notorious, but the reasons for his notoriety aren't specifically
and instantaneously relevant here. Your statement is indirect, but still quite
clearly _praeter hominem_.

~~~
hannibalhorn
I think it is very relevant - the author of "The Cathedral and The Bazaar"
tried out two fashionable new languages, one coming from a corporate team and
one designed by a community ... and went with the Cathedral option. As a fan
of both languages, I just find it very interesting!

~~~
CalChris
I'm not certain how you concluded Go was the Cathedral option. I came to quite
the opposite conclusion: you'd better cross yourself and genuflect in Rust.

~~~
hannibalhorn
Go started out to address the problems of a particular large corporation with
a gigantic C++/Python codebase, and was conceived by a small team of well
respected industry experts.

Rust started out as the new generation engine of an open source browser,
conceding that no existing language met its needs, and has been community
driven since that point, often making breaking changes in pursuit of the
ideal.

Go has indeed been very open to community input, but of the two, it seems
clear that Rust is the bazaar, and Go is the cathedral, no? I'd love to hear
how you arrived at a conclusion to the contrary.

~~~
CalChris
From the outside, Rust and Go were _both_ originally developed by corporations
eventually with community involvement. The credit line for Rust has been
changed from the original _Mozilla_ to the _Rust Project Developers_. Go has
remained Google.

[https://github.com/rust-lang/rust-
packaging/pull/49/files](https://github.com/rust-lang/rust-
packaging/pull/49/files)

But I don't see this corporate history as at all indicative. By comparison,
Unix was originally developed by Ma Bell whereas Lisp was developed by a
community. My view is based more on the resulting languages rather than the
process that got them there.

Again, though, this is from the out outside.

~~~
shmerl
Rust was created before Mozilla got interested in it:
[http://www.steveklabnik.com/history-of-
rust/](http://www.steveklabnik.com/history-of-rust/)

~~~
matt_kantor
For anyone else who gets confused by this empty-seeming page: it's a
slideshow. The right arrow key moves through slides.

------
lhnz
I think this really over emphasises the difficulty in writing code with a
different programming language. The hard part is generally finding a good
solution to the problem you're working on...

When I've worked with Rust, 90% of the time I found it just as easy as working
with something like JavaScript or Python. However 10% of the time it becomes
much much much more difficult. And those times I often end up going in the
wrong direction, reading documentation and trying to apply a solution which
doesn't fit (i.e. no syntax that will make things work because I am
fundamentally doing the wrong thing).

For example, the other day I tried solving a problem in which I had to do an
in-place matrix transposition on some slices and I was getting a bunch of
compile-time errors for everything I tried. I googled later on and found this
[0], which makes it seem like I would have needed to use `unsafe`, however
maybe that's just a misunderstanding and there is a safe way.

People are making it out to be harder than it actually is. The semantics aided
by the compile-time errors make most problems quick to solve. It's very
expressive and gives types which help to avoid fragile code (e.g. `Result` and
`Option`). The only times that it becomes difficult are when you need to reach
for a solution but do not know what to search for, and I think this could be
improved if some of the errors linked to related topics, and once the IDE
support improves.

[0] [https://athemathmo.github.io/2016/08/29/inplace-
transpose.ht...](https://athemathmo.github.io/2016/08/29/inplace-
transpose.html)

~~~
drbawb
Just glancing at that code: the use of unsafe is more or less only there to
avoid initialization & bounds checking. Basically it's an optimization, and I
don't think there's anything there that couldn't be accomplished in safe Rust.

I have an idea as to why the author approached it this way: typically Rust
wouldn't let you take out a mutable borrow to a vector while you're iterating
over it. If Rust _did allow that_ and you modified the collection then the
iterator might reference freed memory!

A common way around this is to just use a typical `for <range>` loop and index
into the array directly to limit the scope of the mutable borrow to _a single
iteration of the loop_ and not _the lifetime of the iterator._ However
indexing in Rust incurs a speed penalty for bounds checking, and the unsafe
code here lets you skip those checks.

Really all the unsafe code is doing is saying: "I promise to initialize `row
_col` entries, and I won 't try to access anything outside `row_col`. Please
don't burn cycles worrying about it Friend Compiler."

It looks to me as though this could've been written as a vector initialized
with all zeroes (which possibly isn't even that expensive, since modern OSes
heavily optimize the case of giving you a zeroed page.) Then in the hot loop
the author could've just used iterators to avoid the bounds check. Using an
iterator for that should be fine in this instance since you're immutably
iterating over one matrix, and the only mutation happening is in the new
transposed matrix.

That all being said: transposing the matrix _in-place_ would run into exactly
that scenario. now you could still do it in safe rust, you would only need to
add the unsafe code if you wanted to turn off the bounds checking for maximal
performance.

------
kibwen
The latter half of the post is pasted from a previous blog post last week,
which has been discussed at length at
[https://www.reddit.com/r/rust/comments/5nl3fk/rust_severely_...](https://www.reddit.com/r/rust/comments/5nl3fk/rust_severely_disappoints_me/)
and
[https://news.ycombinator.com/item?id=13385530](https://news.ycombinator.com/item?id=13385530)
.

TL;DR: we have some concerns. :P

------
didibus
I find his conclusion strange, he counted the score as 3 points for Go in ease
of learning, ease of converting a C code base to it and concurrency. He also
gave Rust 3 points in zero-overhead deployments, better latency and real-time
performance, and better security and safety.

I agree 100% with this scoring. I'm not sure though why he weighted the 3 pros
of Go as more important for NTPsec since the goal of the project are: "Our
goal is to deliver code that can be used with confidence in deployments with
the most stringent security, availability, and assurance requirements." Given
this goal I would personally say that safety, security, deployment ease and
performance are critical, which given his pros and cons would make Rust a
better candidate.

------
dom96
It seems that the author places a lot of emphasis on the maturity and future
prospects of various libraries. I'm surprised that Rust was so quickly
dismissed as tokio seems to have a bright future ahead of it.

What I do think is a fair point is Rust's learning curve. With that in mind I
would like to suggest a third alternative: Nim.

Support for epoll/kqueue/IOCP has been in Nim's standard library for a while
now and is already very mature. The learning curve is probably somewhere
between Rust and Go. In addition Nim also offers a GC that is predictable and
controllable.

~~~
satbyy
Given how demanding ESR is with regards to 10+ years stability, Nim hasn't
even reached 1.0 yet. I love Nim and your contribution to the Nim ecosystem,
but yeah, convincing ESR with 0.16.0 isn't happening.

~~~
nimmer
Nim could be ideal for applications like NTP that require speed, portability
and low memory footprint.

I wonder if the ease of development already outweighs the efforts required to
keep up with the language growth pains and writing wrappers for system
libraries where needed.

------
Animats
One big advantage of Go is that core packages exist for most of the things you
might want to do on a server. Those packages are mostly maintained by Google
employees and are used within Google, so the packages are exercised and
maintained. Rust, like Python, has a large collection of packages maintained
by random people and not under organized maintenance or testing.

"Corrode" needs to get a lot better before it is useful. Look at the Rust it
generates.[1] It transliterates C into unsafe Rust. That's not too helpful.
Doing such a translation well is a hard problem. The translator will need to
figure out exactly what needs to be mutable where, which means building a
graph of the program across function boundaries.

[1]
[https://www.reddit.com/r/rust/comments/4rv0uh/early_stage_c_...](https://www.reddit.com/r/rust/comments/4rv0uh/early_stage_c_to_rust_translator_written_in/)

~~~
AsyncAwait
I am not sure it is possible to auto generate safe Rust code, due to the
nature of C.

~~~
Animats
You'd have to do a lot of flow analysis.

The first step would be to make everything const that can possibly be const.
Const stuff can be borrowed non-mutably. Then make all variables have as
narrow a scope as possible, even if this means putting in more bracketed
blocks. Variables which are not initialized at declaration should be combined
with their first assignment whenever possible.

Then you have to analyze what can have single ownership and what can't. Non-
single-ownership data has to be refcounted. That makes the borrow checker
happy, but may result in excessive refcounting if the analyzer can't track
usage through complex code.

Pointers need to be analyzed for usage. If there's no pointer arithmetic, it
can become a Rust reference, maybe with a "Some" if it can be nil. If there's
pointer arithmetic, the pointer is going to have to be represented as a
reference and a subscript.

You need a standard C library in Rust, with Rust safe equivalents of all the
string functions.

It's a big job, but not impossible. It might be a marketable product.

~~~
Retra
Well, couldn't you then be making a safety-checking tool for C? If you can do
that, it shouldn't be hard to translate from there to safe Rust.

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

I felt this way too but then realized the advanced topics of Go really take
time to get right. Writing correct concurrent code is non-trivial as you need
to tailor your solution to the problem at hand. There is no one size fits all
way to write concurrent code. In some cases a mutex makes sense whereas
channels work better in others.

Programmers must be diligent when using these tools as well because of
deadlocks, data races, or go routine leaks. I think this is an area Rust
excels in with its ownership model that eliminates these problems.

------
justinsaccount
> For comparison, I switched from Rust to Go and, in the same amount of time I
> had spent stuggling to make even a <100 LOC partial implementation work, was
> able to write and test the entire exterior of an IRC server - all the
> socket-fu and concurrency handling - leaving only the IRC-protocol state
> machine to be done.

That's basically my experience with rust and go.

go is stupid, but I can write it. It's stupid needing to write the same for
loop over and over again, but it's an obvious for loop that doesn't have any
surprises, and everyones for loop looks the same.

rust is smart, but I can't write anything in it (yet). Some of rusts features
would be nice to have in go.

~~~
TheDong
> same for loop over and over ... obvious for loop that does'nt have any
> surprises.

Really? Tell me what the output of this short bit of golang code is before
running it then if it's so obvious. The first one is only a for loop, nothing
else, the second output line is a for loop and some channels + goroutines, but
nothing too complicated.

[https://play.golang.org/p/g4Pd5ebrWp](https://play.golang.org/p/g4Pd5ebrWp)

I've seen these issues in the wild more times than I care to admit. Go is a
trashfire. They wouldn't compile in rust.

~~~
dsymonds
Your code is tripping over a complexity of closures, not directly loops. I
don't think you can write a straightforward loop that has confusing behaviour
without also using closures. Your "but nothing too complicated" underplays
that.

~~~
TheDong
My first example did not have a closure. Simplified further:
[https://play.golang.org/p/ttdmropzSu](https://play.golang.org/p/ttdmropzSu)

It's literally about nothing but how the 'value' variable in go for loops is
handled by the language.

To make it worse, a common solution is to do this:
[https://play.golang.org/p/BTRs_TCQdu](https://play.golang.org/p/BTRs_TCQdu)

That code looks like line 10 shouldn't be needed, does nothing, and during
someone elses refactoring it might be deleted and result in the code blowing
up again. No warnings, just silent data corruption.

The second one is a bit complicated, yes, but again I've seen them in the
wild. Again they wouldn't have compiled in rust.

~~~
dsymonds
You're still being clever in that first example. ` _string` is a weird data
type in Go, and `[]_ string` doubly so. You're going out of your way to find a
confusing example, but that's not what the original poster was saying, which
is that you can write a simple loop over and over again that doesn't have
surprises.

~~~
dsymonds
Bah, the HN markup dropped my asterisks in those types.

------
alkonaut
This resonates with me in a lot of ways. I really object to a lot of Go's
design, but I also feel Rust is too much of a struggle at the moment.

When I write performance critical code in Rust I can see how I'm rewarded for
all the mental gymnastics and token salad of Rust.

But when I'm writing something that's difficult or complicated in the
business/algorithm sense but not performance sensitive, then I just can't let
the syntax obscure the semantics.

The code _has_ to look as simple and readable as
ruby/go/Swift/c#/Python/kotlin/Nim -- or the language has failed me.

Right now I feel it's often the opposite. When I write low level Rust code the
type system is usually ok. For higher level code I usually find I need _more_
noise and type overhead (more explicit lifetimes, more Box<Rc<T>>). That I
think is a big problem.

Rust, like C++ is "you pay for what you use" \- but what they mean is
performance. I wish it was readability. I almost wish the _default_ was a
higher level language with lots of heap allocation etc, and you explicitly
declare when you don't want that (c.f C# unsafe/stackalloc and similar)

~~~
pcwalton
> I almost wish the default was a higher level language with lots of heap
> allocation etc, and you explicitly declare when you don't want that (c.f C#
> unsafe/stackalloc and similar)

I don't know if that's really possible. Aliasable mutation just doesn't play
well with the kind of memory model that Rust has. If you introduce
unrestricted aliasing and mutation like most other languages, then you're
going to get a flood of confusing borrow checking errors.

~~~
alkonaut
Hi Patrick, I appreciate you taking your time to object to blurbs that aren't
thought through.

I suppose what I'm trying to say is that I'd really like simple code to look
simple, and that it's an explcit design goal that code look as simple as
possible. Perhaps I'm spoiled by languages that hide memory complexity with a
pervasive GC (I am) but I still think there has to be room for improvement
(and to be honest there probably are tons of already created issues with
possible lifetime elision or coercions that reduce the need for Boxes inside
Rc's inside boxes...).

Keep up the good work.

------
jupp0r
I find the argument that of not being productive in a language in a matter of
a few weeks to be quite weak. Programming languages are tools. Tools take time
to learn.

Nobody would consider a flute to be an instrument superior to a violin because
it can be learned faster. Rust is a tool that takes time to learn. Is it worth
it? How could ESR decide if not in hindsight?

My personal experience is that understanding and applying Rusts borrowing and
ownership made me a much better systems programmer in C and C++. Would I write
a production NTP server in Rust or Go? Definitely Go, but that's no reason to
dismiss the concepts and the remarkable engineering of Rust.

------
eridius
ESR seems to care really strongly about concurrency things being "primitives"
in the language. Why? There's nothing wrong with them being part of the crates
ecosystem. Maybe in 10 years the crate you chose won't be under active
development, but it's not like crates will just mysteriously break once they
reach a certain age. As for the language itself being stable, sure, a program
you write today might not compile using the latest compiler in 10 years, but
it should still compile using the last 1.x release, so it's not like you won't
be able to compile your project in 10 years.

------
eridius
Something I'm surprised ESR didn't consider is the fact that Rust lets you do
a piecemeal translation. You can rewrite individual functions in Rust and call
them from C very easily. So you don't need to rewrite all 62KLOC at once.

~~~
mixedCase
Go more or less allows you to do the same, but I've heard there are some pain
points.

In any case, Rust would probably require some rearchitecturing anyway.

------
pimeys
I disagree with many points in this article, but being writing Rust in my
company since summer I can definitely say it is much harder than any other
language I've used. Now when I learned doing a synchronous service with it
Tokio was released and I've been banging my head against the wall to get the
concepts.

But then again, it just takes time. And I have some crazy two month uptimes
with my rust services eating that constant 8 megabytes of ram...

~~~
pimeys
Adding to this. It's not at all waste of my time to do hard things with Rust.
Learning is important and when my employer pushes me to that direction, I'm
quite happy writing Rust.

------
vog
I'm surprised this article is from 2017. It seems that esr doesn't account for
the latest (huge) improvements of Rust during the last year.

Given that Rust is younger than Go, ignoring a year's worth of development
makes for an especially unfair comparison.

The issues he cited were from 2014 and 2015, regarding Rust for networking
code. Moreover, on his blog post
([http://esr.ibiblio.org/?p=7294](http://esr.ibiblio.org/?p=7294)) he received
a clear answer that he seems to have ignored:

    
    
        Stefano:
        
        [...]
        For epoll: There is a crate. You could also use
        future-rs or tokio. So you have three possibilities.
    

Finally, the author of another networking project, _TRust-DNS_ , used these
Rust features and was quite satisfied with the elegance of the resulting code:

[https://bluejekyll.github.io/blog/rust/2016/12/03/trust-
dns-...](https://bluejekyll.github.io/blog/rust/2016/12/03/trust-dns-into-
future.html)

~~~
tom_mellior
> So you have three possibilities.

More possibilities isn't necessarily better. ESR makes precisely this point:
"While implementations exist in the crate system, there is not yet any
guarantee that any of the alternatives will be maintained over 10-year
timescales."

Having three possibilities just makes it more likely that you pick the wrong
one, the one that will be dropped by its maintainers because the rest of the
community chooses another one.

------
k__
When I first read about Rust and Go they were both advertised as C/C++
killers.

But I have the feeling Go became more of a Python/Node.js alternative.

~~~
zaphar
A lot of this is because Google used C++ where other people were using Python
or Node. It was made to "kill" C++ at Google more than outside of it.

------
CalChris
Rust is hard to write but I'll grant that once written it is relatively easy
to understand. That's kinda the opposite of C++ where it's easy to write and
hard to understand (although it's easy to think you understand).

I appreciate the safety+performance value proposition in Rust. More cathedral,
less bazaar.

~~~
iopq
Not THAT easy

    
    
        fn apply<A, B, C, F, G>(mut f: F, a: A) 
        -> impl FnMut(&B) -> C // must still be `for<'r> impl FnMut(&'r B) -> C`, because that’s what filter requires
                 where F: FnMut(B) -> G, // must not be `for<'r> FnMut(&'r B) -> G`, because regular functions do not implement it
                       G: FnMut(A) -> C,
                       B: Copy, // for dereferencing
                       A: Clone {
        
            move |b| f(*b)(a.clone()) // this must do any bridging necessary to satisfy the requirements
        }
    

this function signature must be EXACTLY like what I wrote or it won't work

~~~
CalChris
No, not that easy especially when you get to the functional programming stuff.
But I find FP hard to understand since I don't use it much.

> this function signature must be EXACTLY like what I wrote or it won't work

This can be seen as a feature in the sense that you can't program by luck:
_well, this incantation seems about right and the compiler nods its head that
it understands and that means_ something _, so it must be right_.

~~~
iopq
Joke's on you: it took me a month of asking around why my program won't
compile to figure out I really CAN'T do it without dereferencing inside the
function. This is because of higher ranked lifetime bounds... there's no way
to express the correct lifetime bound in this case (in Rust, maybe in Haskell
it's possible), so you just have to deref first.

~~~
openasocket
> This is because of higher ranked lifetime bounds...

No, it's because the function you're returning is of type FnMut(&B) -> C, but
your F function is of type FnMut(B) -> G. It expects an owned value of B, but
you only have a borrowed reference to a B. Just make F of type FnMut(&B) -> G
and you no longer have to dereference and no longer need the restriction that
B: Copy. Higher-ranked lifetime values don't have anything to do with it.

Here's the new version:

    
    
      fn apply<A, B, C, F, G>(mut f: F, a: A) 
        -> impl FnMut(&B) -> C
                 where F: FnMut(&B) -> G,
                       G: FnMut(A) -> C,
                       A: Clone {
        
            move |b| f(b)(a.clone())
        }

~~~
iopq
You think I didn't try that one before? It doesn't work in MY case:

    
    
        error[E0281]: type mismatch: the type `fn(_) -> _ {tool::second::<_>}` implements the trait `std::ops::FnMut<(_,)>`, but the trait `for<'r> std::ops::FnMut<(&'r _,)>` is required (expected concrete lifetime, found bound lifetime parameter
    
          --> src\lib.rs:50:17
           |
        50 |         .filter(apply(second, i))
           |                 ^^^^^
           |
            = note: required by `apply`
    
        error[E0271]: type mismatch resolving `for<'r> <fn(_) -> _ {tool::second::<_>} as std::ops::FnOnce<(&'r _,)>>::Output == _`
          --> src\lib.rs:50:17
           |
        50 |         .filter(apply(second, i))
           |                 ^^^^^ expected bound lifetime parameter , found concrete lifetime
           |
           = note: concrete lifetime that was found is lifetime '_#11r
           = note: required by `apply`
    
        error: aborting due to 2 previous errors
    
        error: Could not compile `fizzbuzz`.

------
mike_hearn
I wonder why it was only Rust or Go he considered.

He could also use Java. It has a 'pauseless' GC in Fedora Core's OpenJDK
(Shenandoah). It has an epoll abstraction in the core library. It has
libraries for doing things like async DNS requests already.

It would be nice sometimes if these A vs B comparisons were a bit wider.

~~~
tomp
It's not pauseless.

> Shenandoah is an ultra-low pause time garbage collector that reduces GC
> pause times by performing more garbage collection work concurrently with the
> running Java program

Funny enough, the term "pauseless" was in fact invented precisely because of
people like you, who abused the original terms ("concurrent" or "asynchronous"
[0]) used for garbage collectors that never "stop the world", and used it for
algorithms that merely run in parallel with the mutator threads, pausing them
every so often. The next term used was "fully-concurrent" and now "pauseless".
But if you keep abusing these terms to mean _not_ fully pauseless/concurrent
GCs, then it will become just as useless as all the terms before it.

[0] [http://gallium.inria.fr/~xleroy/publi/concurrent-
gc.pdf](http://gallium.inria.fr/~xleroy/publi/concurrent-gc.pdf)

~~~
mike_hearn
I put "pauseless" in quotes because I know it's not entirely pauseless. It's
described as "ultra low pause time" by the original project.

However, whether we like it or not, Azul has established the term "pauseless"
as the way to describe their own collector which before Shenandoah was the
only GC that can realistically be described that way, and which Shenandoah is
very similar to. This is despite the fact that Zing still pauses.
Specifically, the GC moves objects whilst the program runs.

I am unaware of any GC algorithms that are truly, completely pauseless in
every situation. So I don't know what you want the term to be reserved for.

------
merb
well actually he says that DNS lookups etc needs to be asynchronous, but
aren't go's channels blocking?

I mean he also says that rust has no good epoll/select abstraction, which is
wrong. And also "a welter of half-solutions in third-party crates but describe
no consensus about which to adopt" I think he didn't researched well enough.

I mean it would be the same as saying that there is no good way to create a
custom non blocking dns server with pure java/scala (no external library
used). Rust has [https://tokio.rs/](https://tokio.rs/) and everbody who even
looked into network services with rust, stumbled across it.

Well maybe for his goals and contributor base go is prefered and that is ok,
but well this article is more or less written as a rant against rust, that
he/she/it does not agree with the generel design/documentation/whatever of
rust.

In fact I also think that the tooling of rust sucks. rust is a language which
shines with extremly good tooling. I mean rust has a godlike package manager
and every tooling gets better and better.

Compared to go where the package management just sucks but the tooling even
IDE completion is extremly great.

P.S.: I would not want to have a garbage collected ntp server. But for a lot
of things I thing Go would be a good fit, even when it would not be my tool of
choice.

~~~
bluejekyll
> has no good epoll/select abstraction, which is wrong

I can't reiterate this enough. Rust has one of the best abstractions I've ever
used over epoll/kqueue and MS' variant, MIO. MIO has picked not the crappy
POSIX select, which every major OS has a better alternative to now, but
instead the OS' preferred event system. The 10 year stability requirement is
awkward, as I don't think anyone can predict the future, and in 10 years, who
knows what will change.

As you mention, tokio is an awesome futures based abstraction on top of that,
making it a breeze to write complex, fast, event driven logic.

I'm sad that after four days he didn't like Rust, I had a 100% different
experience. After one day I fell in love with nearly every aspect of the
language, and it was specifically because of state machines (which they
mention as one of their core desires). My biggest complaint against the
language hasn't changed, which is dealing with different Error types, but even
that after a lot more experience with Rust has become easier.

Anyway, for NTPSec it's sad that this didn't suit their desires, but that
doesn't mean that we can't write our own.

~~~
zbobet2012
Go's epoll abstraction is baked into the runtime. They are called goroutines.
Goroutines blocked of FD's automatically use epoll and schedule based on its
results:
[https://github.com/golang/go/blob/master/src/runtime/netpoll...](https://github.com/golang/go/blob/master/src/runtime/netpoll_epoll.go)

~~~
bluejekyll
I wasn't commenting on go, just pointing out the library that most people in
Rust are using for async-io.

------
spullara
They are two entirely different use cases. Rust is for replacing C/C++ with a
safer alternative. Go is basically for developers that never fell in love with
Java or C# but need the same kind of language.

~~~
endorphone
Do those usage distinctions really hold? We all know the mythology that Go was
created as a replacement for C++ (the Go FAQ still lists it as being created
because of the poor system language tools). Rust targets largely the same
problem space. They're both compiled languages that in an idealized world
could offer C levels of speed.

Go also offers a lot of high level constructs that allow you to create a web
server and other solutions traditionally built in higher level platforms, but
that doesn't reduce its low level functionality.

~~~
spullara
Rust can call and be called by C code without a translation layer. To me, this
is a requirement for any language that is truly going to replace them. Also,
Go went down the GC path which limits its applications to those where you can
have unpredictable pauses and for me firmly places it in the Java/C# part of
the spectrum.

~~~
endorphone
I'm not attempting to advocate Go here (they're both fantastic options), but
any application running on a non real-time OS can have unpredictable pauses.
That's the world of preemptive multitasking. Of course this is a scale thing
(Go doesn't escape those OS pauses), but Go 1.8's own pauses are in the sub-
millisecond range.

C# and Java have pauses in the hundreds of millisecond range (though there are
"real-time" JVMs that greatly improve this). And it's notable that Go goes to
lengths to avoid generating garbage.

------
jeffdavis
I am learning rust. To me, the amazing thing is the lack of runtime.

If you are writing a library to render the latest web image format, or
implement the latest secure network protocol, then your choices are limited
and Go is not an option.

Sure, you could write it in Go and then Go programmers could use it.

But if you write it in C or rust, it could be the de facto library for nearly
all languages.

The article is a good one, but doesn't really influence my personal opinion
much.

------
deathanatos
> _things that should be dirt-simple in Rust, like string concatenation, are
> unreasonably difficult_

This is how hard adding String objects is in Rust:

    
    
      a + b
    

A more full example shows only small complexity, really, and I include it only
for completeness and fairness:

    
    
      fn main() {
          let a = String::from("Hello,");
          let b = " world.";
    
          let c = a + b;  // this is the only part that concats, really.
    
          println!("{}", c);
      }
    

The String::from call converts from a str& — which is effectively a pointer
and length to UTF-8 data, to a managed string, more akin to std::string in
C++; str& doesn't implement +, I presume b/c it doesn't know what the
resulting type should be (and doesn't presume).

A C programmer should easily comprehend why you can't simply add two char * s
together; compare:

    
    
      char *new_string = malloc(strlen(a) + strlen(b) + 1);
      if(!new_string) { abort(); }
      stpcpy(stpcpy(new_string, a), b);
      return new_string;
    

(that's just the `a + b` line from Rust, in C, essentially)

(hopefully I got that right. stpcpy avoids an extra iteration through a that
strcat cannot; I do know about strcat.)

Essentially, in all of Python/Go/Rust, if you has the right type, string
concatenation is `a + b`.

> _Contemplate this bug report: Is there some API like
> "select/poll/epoll_wait"? and get a load of this answer:_

> > _We do not currently have an epoll /select abstraction. The current answer
> is "spawn a task per socket"._

It would need to be cross-platform; so I can understand why Rust isn't there
yet _in the standard library_. There are third-party libraries out there that
do this. (And C has nothing here, either…)

You can always call epoll directly, and write the required abstraction
yourself. (There are even third-party wrappers for calling epoll, so you don't
even have you write _that_ yourself either; see the excellent "nix" library.)
If you want a 10 year solution…

> _Relatedly, the friction cost of important features like the borrow checker
> is pretty high._

At first, this is true. Then I felt like I started realizing that what all the
"friction" of the borrow checker was _it pointing out serious bugs in my
code_.

Regardless, NTP would be better off in _either_ Rust or Go instead of C, IMO.

~~~
EdiX

        fn main() {
          let a = "Hello,";
          let b = " world.";
    
          let c = a + b; 
    
          println!("{}", c);
        }
    

And the result is:

    
    
      rustc 1.15.0-beta.3 (a035041ba 2017-01-07)

error[E0369]: binary operation `+` cannot be applied to type `&str` | 5 | let
c = a + b; // this is the only part that concats, really. | ^ | note: an
implementation of `std::ops::Add` might be missing for `&str` | 5 | let c = a
+ b; // this is the only part that concats, really. | ^ timeout triggered!

What?

PS. looks like hacker news can't handle rustc error format, a pity...

~~~
okey
As the post you are responding to pointed out, String::from converts from a
string slice to a String. You didn't do this.

Your code fails to compile because it attempts to apply + to two string
slices, and that is not implemented. @deathanatos also mentioned that.

You might find the Rust book page on Strings helpful: [https://doc.rust-
lang.org/book/strings.html](https://doc.rust-lang.org/book/strings.html)

------
jnwatson
I'm curious if some of this is the fact that a lot of senior folks are
learning new languages for the first time in a long time. I think we
unnecessarily constrain language design if they have to look like everything
that came before.

I remember learning Java was a piece of cake. Go was too. Both were remarkably
similar to previous languages I knew. Rust was/is a lot more difficult, but
nowhere close to the mindfuck that is Haskell or ML.

I mean, is it that bad that it takes a month to really learn a new language if
it can provide worthwhile benefits?

~~~
wasted_intel
This.

------
luckystarr
Its true, coding in Rust makes you feel like a total moron at first. The
experience actually reminded me of the time when I first picked up
programming.

It only takes around a week or so though, after that you can be surprisingly
productive. I never would allow myself to write the code in C that I wrote in
Rust. I'm just not clever enough.

------
shmerl
_> The amount of complexity and ritual required by Rust’s ownership system is
high and there is no other language I know of that is really good preparation
for it._

C++ helps, if you are familiar with RAII usage in it.

------
VexorLoophole
The main problem i have with rust is that there is no real book for beginners.
Sure thing there is the RustBook and RustByExample. But i need something to
guide me. I dont want to slap things together. I want to learn how to do it
right. All Rust recourses i found only told me how to do XXX in Rust. Nothing
along the lines of: This is could be a real world example for YYY. In
examples, you will always only find excessive .unwrap() use and functions
which dont borrow anything.

Had the same feeling with go. Looking into big projects like syncthing helped
a bit. But first i have to get a better hang of the language. Books like
"Atomic in Scala" or "Clojure for the Brave" are taking your hand and guiding
you through the Language. Even when taking a peak into books like "21st
century C" i learned more, then when i simply force myself through go's "Gopl"
or Rust's Book. I know i am probably not the right target group. But i really
want to learn one of those languages in my free time, and i had a really hard
time to do so.

After understanding go better, i still want to switch to rust. The build
system with cargo pleases me and looks somehow cleaner as in go. I just create
a project with 'cargo new XXX --bin' and start coding and building some kind
of lib in my project. No problem. I go there are 100 different ways to start a
project, and most time you will only find people complaining about vendoring
etc.

~~~
rshm
Its a work in progress, but available bits were helpful.

[http://aturon.github.io/](http://aturon.github.io/)

~~~
VexorLoophole
Thanks a lot! Dindn found this one till now!

------
iopq
This isn't anything different from the other two articles he wrote. What's the
point of writing a third one saying the same things?

------
gwenzek
The title should have been "Rust vs. Go, by a Go developer who doesn't know
Rust". Would have saved me 5 minutes.

------
julian_1
Stronger typesystems are better for production system. They give more
guarantees and mean you need to write less unit tests. Rust's sum/algebraic
types are a move in the right direction and so is pushing resource usage
invariants into the typesystem.

------
onionjake
I hope that the measure of whether something is good enough for the embedded
space is not android.

I have quite a few openwrt routers running with substantially less resources
available to it than the worst android phones.

I don't know if go would be able to meet the cpu/memory constraints in that
environment... from the blog post it seems like that wasn't even measured?

------
disordinary
One of the interesting things about Rust is that it can compile C libraries,
so you can move a code base from C to Rust one module at a time.

------
jug
I think Go and Rust are interesting languages because both tackle the "C
successor" problem and both feel like good solutions, yet so different from
each other that it almost feels like they aren't meant to be used for the same
problems. How could that happen?

I think it's largely because C and C++ has been used in such a wide variety of
applications as "good enough" languages but where there were so much room for
improvement, for modernization. We're talking about an old assembly language
layer and an object orientation cludge on top of that layer. As soon as you do
improve on these, you observe that the application space to cover for
successors is huge, so huge that there is plenty of room for two different
languages.

Developing in Go doesn't feel like Java or C# to me. It feels more like C (and
definitely not C++) and I love that. It's so simple, yet producing native
code. It's like what you'd get if you took C and from the very start decided
the productivity vs performance problem favored a garbage collector, prefering
productivity. Then looked at how common and underutilized multicore CPU's are,
while at the same time how synchronization is hard to get right. If you then
move from these problems to solve and realize the GC is your Achille's heel
and simply try to optimize the heck out of that, I guess you get something
like Go.

Meanwhile, Rust during the design phase must have been in such a similar place
as Google engineers were when designing Go? Once again, C / C++ were flawed
and unsafe, cumbersome to work with. They took the very same productivity vs
performance problem and this time saw that, no, we don't want garbage
collectors, we prefer performance supporting time critical systems above all
in the spirit of C, yet safety. Then looked at common crash issues and went by
that, and then they got Rust.

Personally I prefer Go. It's the most fun for me to work with and feels like a
very pragmatic language. Rust feels more like an academic language to me:
ideas and exciting concepts allowed to materialize. It also has its place, but
seems like more in niched scenarios like real time systems and device drivers,
low level, critical stuff like that.

------
scotty79
Semi-related, side-by-side comparison of how common things are done in rust
and go:

[http://rosetta.alhur.es/compare/Rust/Go/#](http://rosetta.alhur.es/compare/Rust/Go/#)

------
camus2
The problem with Rust is that Rust cannot be understood by someone who never
had to do manual memory management. So people coming from Java, Ruby, Python,
Javascript, PHP who have never used C or C++ will never understand why Rust
handles variables the way it does. Rust cannot be popular among these people
because Rust doesn't solve their immediate problems in terms of performances.

the Rust team often pretends they are open to suggestions as to how to make
Rust easy or easier to learn, that's impossible given how memory management is
done in Rust, especially in regard of the people i talked about in the former
paragraph.

Only a developer familiar with C or C++ can appreciate Rust semantics. The
others cannot.

~~~
phaylon
I feel that that's not really true. I'm from a dynamic language background and
I didn't have many problems. Quite the opposite actually, as to me the Rust
compiler was more of a teacher at first. I've tried getting into C and C++ a
couple of times in the past, but since I started using Rust I finally started
understanding some of the concepts and issues from those languages that I had
a hard time grasping earlier.

~~~
camus2
> I've tried getting into C and C++ a couple of times in the past

You just proved my point. You did get into C and C++ before trying Rust.

~~~
phaylon
No, I _tried_ and failed. I've never made it anywhere close to writing my own
C or C++ code, and failed at the tutorial stage or earlier.

~~~
camus2
But you wrote a malloc, free, new or delete before. it's not like you were
oblivious to these concepts, that's exactly my point.

~~~
phaylon
Yes, but I didn't understand the implications or background. If the
prerequisite for having enough basic knowledge is "making it halfway through a
C tutorial" it doesn't seem as much of a hindrance as your top comment
suggested.

------
adelarsq
Funny article. This is something like emacs vs vim by someone that knows only
one editor

------
yellowapple
I'm curious about whether and how Rust "dealbreaking" situation compares to
C/C++. Seeing as how Rust is designed to be a replacement for those two (so is
Go, but it seems to be at a much higher level), I reckon that'd be the more
fair comparison.

In particular, it's my understanding that epoll and select are system calls.
In that case, just call them. Or is there really no means to do so from Rust
(doubtful)? Sure, you'd have to wrap stuff in "unsafe" calls, but that's par
for the course when interfacing with non-Rust software.

------
gok
So the author doesn't care about memory usage or throughput, except for a few
"soft realtime" sections? Why would either Rust or Go be better for this task
than something like Java or Python?

~~~
xemdetia
Java is not really a great choice because you need a JVM for the task at hand.
Python is not a good choice because of concurrency constructs, and it's clear
that the goal of this was to self-contain the whole thing and not have fringe
packages in a semi-direct port from C to a different language. For a raw
systems daemon that needs to run on mostly everything being coupled to only
one runtime is a huge boon for portability.

~~~
gok
That disqualifies Go even more so. You could easily embed a competent JVM in
the space a typical Go binary requires to embed all its libraries (the
"docker" binary I'm looking at is 13 MB). Go's "Hello, world" is well over a
megabyte.

~~~
xemdetia
The critical feature here is that the resulting Go binary is whole and
complete and tightly coupled to the system at hand, which fits more the output
from Rust or C. Inherently Java software is dependent on two runtimes, the JVM
and the core libraries the JVM is compiled against. Space isn't the most
critical concern here, it is portability and bringing a JVM everywhere is
really painful and really a project well outside the goals of the software
described. If a JVM was going to be considered a solution this project would
have to package the JVM and the daemon which would be silly.

------
maxekman
My favorite feature of Go is the immediate productivity that almost any
developer can achieve within days af seeing the language for the first time.
That adds tremendous business value to any project.

------
charlesholbrow
In the last post didn't he say that he spend 15 years writing in 'C' and
learning the ins and out?

I don't think 4 days is enough to really evaluate a language. I'm not going to
dismiss Rust based on this analysis.

------
EugeneOZ
Rust fans are trying to avoid "vs" articles, would be great to see such
endeavor from Go fans too.

~~~
treehau5
I am a go fan, and when I saw this article on the fp, I said to myself "here
we go again"

It's the 4th law of HN: Wherever Rust is, Go goes, and vice versa.

I am considering just accepting this reality that people will always pit these
two against each other, and maybe just accept it for it's positive merits:
that the extra competitiveness will help create a better ecosystem for the two
of them.

~~~
EugeneOZ
Constructive comparisons with deep knowledge of both languages are priceless,
when articles "I tried Go/Rust 1 week and didn't get it" are useless. Title
"vs" often is a marker of articles of the second type - just to share
emotions, not knowledge.

~~~
Turing_Machine
"Constructive comparisons with deep knowledge of both languages are priceless,
when "I tried Go/Rust 1 week and didn't get it" are useless."

Well, unless you want people to actually use your shiny new language. If
that's the case, perhaps criticisms of this type should not be dismissed out
of hand. :-)

Most programmers are going to abandon something if they study it for a week
without significant results. Maybe they'll keep plugging at it if their boss
orders them, but they won't do it on their own. Oh, sure, there's a small
subset of programmers who enjoy tinkering with weird languages for fun, but
that subset is dwarfed by the number of programmers who view languages as a
tool for _getting things done_.

If there's anything that we should learn from the history of programming
languages, it's that usability trumps theory every time. The languages that
people actually use are almost never the ones that theoreticians admire.

Note that most code today is written in C, JavaScript, PHP, Java (none of
which would win any prizes for theoretical elegance)... rather than ALGOL, ML,
Haskell, the various Wirth languages...

There's really no comparison. Lisp probably comes closest, in that it is both
theoretically elegant _and_ has been used, by the programmer's choice, to
build large real-world systems, but even Lisp is basically a rounding error.

~~~
mseepgood
> Note that most code today is written in C, JavaScript, PHP, Java (none of
> which would win any prizes for theoretical elegance)... rather than ALGOL,
> ML, Haskell, the various Wirth languages...

ALGOL wasn't actually that bad.

~~~
Turing_Machine
That was long before my time, but from what I've read ALGOL's problems were
that it was too complex to be easily implemented on the (very limited)
hardware of the time, and a focus on theory to the extent that basic
functionality was ignored (even I/O!). That made it great for writing down
algorithms on paper, but troublesome if you actually wanted to use it.

~~~
mseepgood
Algol 68 was too complex, but Algol 60 was quite good and successful.

------
noway421
It feels like this guy will end up converting the codebase to both languages.

Which would ultimately be fun to follow

------
hoodoof
Hey wow this new technology will solve all our problems with that old
technology!

------
tree_of_item
I don't understand why esr thinks his opinion after 4 (four!!) days of Rust is
interesting. Am I the only one here who spends a lot longer with a language
than that before passing judgement on it?

~~~
detaro
At the minimum, it is something to point at when he gets asked why his project
doesn't use Rust, which probably comes up quite a lot.

------
general_ai
I wrote less than 2 KLOC of Go in my life (at Google, because I needed a web
server for an internal dashboard, and Java was too much pain), and one thing
is for sure: while I did not like the language per se, I did not hate it
either, and I was able to get used to it in about 3 days, which is how long it
took me to write the code. I literally knew nothing about it at the outset,
and I felt comfortable in it after writing less than 2KLOC. I can't think of
another high performance language with such a short learning curve.

I've tried Rust and concluded that it solves problems I don't have. I work
mostly in C++ (more like C+, I tend to keep my code pretty simple), and with
unique_ptr<>s, shared_ptr<>s and judicious use of concurrency primitives I can
avoid pitfalls well enough that I maybe encounter a self inflicted concurrency
or memory management issue once every six months, if that. And it pays
amazingly well, and there's an enormous number of libraries available. That
said, when I need a high performance web server, I'll use Go without
hesitation. When performance doesn't matter, Python and Flask are pretty
indispensable.

~~~
koffiezet
As an (ex-)C++ developer, this is mainly my feeling too. Rust solves many
problems in a very elegant way, but those problems are things that most
experienced/skilled C++ developers solved by sticking to a fixed set of best
practices, mostly avoiding these problems.

Most C++ developers I talk to about Rust express the same sentiment, they
usually like the idea, but aren't personally interested in learning it because
it solves problems they're rarely confronted with.

I tried picking up Rust a few times since it does interest me, and I like
trying and learning new things, but I currently don't have the time to really
dive into it. Go on the other hand took no time at all to get into, and was
promoted pretty quickly into one of the more frequently used tools in my
toolbox, just like Python.

~~~
general_ai
As C++ developers, though, we are a biased bunch. C++ takes years to properly
learn and gain confidence with, something we're completely oblivious to since
that learning curve is in the past. I concede that for people who don't
already know C++, Rust may be a good choice.

------
hubert123
I cannot agree more with his conclusions about Rust, you can overlook a lot of
problems. But the language itself is just such an arcane pain to deal with,
the author really brought this out: Even just writing and printing few lines
of strings out has possibly hours of gotchas in it. Add a little IO and you're
looking at days. It's not a question of a lack of documentation, I just think
the language is _weird_. I truly wanted Rust to be great and I keep looking at
it wanting it to be better but it just isn't. Isn't it funny how in the real
world, suddenly the so lauded 'type safety' really just doesn't matter that
much in practice. A simpler language overall would have made a much bigger
impact than any generics.

~~~
neurotrace
>Isn't it funny how in the real world, suddenly the so lauded 'type safety'
really just doesn't matter that much in practice.

I've been writing Javascript for years and if there's one thing I've learned
it's that type safety matters on the large scale. Don't get me wrong: I
actually love Javascript. It's my go-to tool when I want to just get things
done. But when you start scaling things out and get a lot of moving parts
going, type safety really helps lift the mental burden of tracking everything
yourself. That's why TypeScript is so popular.

I've been a huge fan of dynamically/weakly typed languages for a while but
I've fallen in love with Rust. Yes, it can be a bit painful at the start but
it doesn't take hours to get basic IO working and it's quite beautiful once
you get into it. The mind-bending part is the ownership model because nothing
else has ever had something like that. But, you know, that's just my opinion.

------
hnbro
it's unfortunate that rust seems barely more than a compiler. it's... empty.
the "ecosystem" feels like a namespace-free dogpile of college spring break
experiments. a wasteland of pre-pre-pre-pre-alpha 0.0.0.0.0.1 stuff. it'll be
10 years before it improves to even being underwhelming.

in go, you can download it and have the pieces to actually do useful stuff
right away. legit productivity. not to mention putting together graphs or
graph-like structures and other similar things aren't the obtuse sphinx
riddles they are in rust.

------
user5994461
There are real world jobs requiring Go (and it's growing slowly). There are no
jobs requiring Rust.

End of the comparison. That's all one needs to know if he's interesting in a
career in distributed systems.

~~~
neurotrace
That's a terribly unfair comparison. Go 1.0 came out just about 5 years ago
and Rust 1.0 only came out a year and a half ago. Not to mention, there are
people employed to write Rust. Most notably, the Servo team.

~~~
AsyncAwait
Also MaidSafe is an all-Rust team.

