Rust vs. Go - <AUTHOR> https://blog.ntpsec.org/2017/01/18/rust-vs-go.html <comment><USER3> 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 - <USER2> > 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.

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

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

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

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

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

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

</comment></comment></comment></comment></comment></comment></comment><comment><USER10> 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.

<comment><USER11> 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)

<comment><USER12> _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.

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

<comment><USER12> _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.

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

</comment></comment></comment></comment></comment></comment><comment><USER14> 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?

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

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

<comment><USER17> 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)

</comment></comment></comment></comment><comment><USER18> 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.

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

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

<comment><USER19> Ah, right. It does.

</comment></comment></comment></comment><comment><USER21> 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.

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

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

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

<comment><USER21> 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

</comment></comment></comment></comment></comment><comment><USER24> > 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.

<comment><USER25> > 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?

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

</comment></comment></comment><comment><USER26> 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.

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

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

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

</comment></comment></comment></comment><comment><USER29> 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!

<comment><USER30> 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_.

<comment><USER29> 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!

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

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

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

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

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

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER34> 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)

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

</comment></comment><comment><USER23> 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

</comment><comment><USER21> 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.

</comment><comment><USER35> 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.

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

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

</comment></comment></comment><comment><USER38> 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/)

<comment><USER39> I am not sure it is possible to auto generate safe Rust code, due to the nature of C.

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

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

</comment></comment></comment></comment><comment><USER41> > 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.

</comment><comment><USER42> > 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.

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

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

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

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

<comment><USER44> Bah, the HN markup dropped my asterisks in those types.

</comment></comment></comment></comment></comment></comment><comment><USER45> 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)

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

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

</comment></comment></comment><comment><USER46> 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.

</comment><comment><USER47> 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.

</comment><comment><USER47> 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.

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

</comment></comment><comment><USER49> 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...

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

</comment></comment><comment><USER50> 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)

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

</comment></comment><comment><USER51> 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.

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

</comment></comment><comment><USER31> 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.

<comment><USER53> 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

<comment><USER31> 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_.

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

<comment><USER54> > 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())
        }

<comment><USER53> 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`.

</comment></comment></comment></comment></comment></comment><comment><USER55> 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.

<comment><USER56> 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)

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

</comment></comment></comment><comment><USER57> 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.

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

<comment><USER59> 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)

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

</comment></comment></comment></comment><comment><USER60> 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.

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

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

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

</comment></comment></comment></comment><comment><USER62> 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.

</comment><comment><USER63> > _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.

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

<comment><USER65> 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)

</comment></comment></comment><comment><USER66> 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?

<comment><USER67> This.

</comment></comment><comment><USER68> 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.

</comment><comment><USER32> _> 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.

</comment><comment><USER69> 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.

<comment><USER70> Its a work in progress, but available bits were helpful.

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

<comment><USER69> Thanks a lot! Dindn found this one till now!

</comment></comment></comment><comment><USER53> 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?

</comment><comment><USER71> The title should have been "Rust vs. Go, by a Go developer who doesn't know Rust". Would have saved me 5 minutes.

</comment><comment><USER72> 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.

</comment><comment><USER73> 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?

</comment><comment><USER74> 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.

</comment><comment><USER75> 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.

</comment><comment><USER76> 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/#)

</comment><comment><USER77> 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.

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

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

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

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

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

</comment></comment></comment></comment></comment></comment><comment><USER79> Funny article. This is something like emacs vs vim by someone that knows only one editor

</comment><comment><USER80> 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.

</comment><comment><USER81> 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?

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

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

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

</comment></comment></comment></comment><comment><USER83> 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.

</comment><comment><USER84> 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.

</comment><comment><USER85> Rust fans are trying to avoid "vs" articles, would be great to see such endeavor from Go fans too.

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

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

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

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

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

<comment><USER88> Algol 68 was too complex, but Algol 60 was quite good and successful.

</comment></comment></comment></comment></comment></comment></comment><comment><USER89> It feels like this guy will end up converting the codebase to both languages.

Which would ultimately be fun to follow

</comment><comment><USER90> Hey wow this new technology will solve all our problems with that old technology!

</comment><comment><USER91> 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?

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

</comment></comment><comment><USER93> 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.

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

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

</comment></comment></comment><comment><USER95> 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.

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

</comment></comment><comment><USER97> 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.

</comment><comment><USER98> 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.

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

<comment><USER39> Also MaidSafe is an all-Rust team.</comment></comment></comment>


Chatbot AI constructor with no programming - <AUTHOR> http://chatfuel.com <comment><USER2> Am i seeing that right that it only supports Telegram? :/

<comment><USER3> Looks like temporarily, but they have a list of other chat services they intend to support soon at the bottom of the page.</comment></comment>


Rust for Clojure Programmers - <AUTHOR> https://gist.github.com/oakes/4af1023b6c5162c6f8f0 <comment><AUTHOR> I love the way this begins:

"You already write software in Clojure. It pays your bills. You enjoy it. You're in an industry reaping disproportionate benefit from loose money policies, leading to a trend-chasing culture of overpaid nerds making web apps. You feel guilty about this, but there is nothing you can do about it because you have no other talents that a rational person would pay you for.

"Learning Rust will probably not do much to solve that problem for you. It won't assist you in making the ontological leap from a tired stereotype into something sentient and real. You will remain a replaceable silhouette with no discernible identity. It might even exacerbate the problem. However, it will give you a useful tool for writing low-level software."</comment>


DNA Is Only One Among Millions of Possible Genetic Molecules - <AUTHOR> https://www.sciencedaily.com/releases/2019/11/191111084915.htm <comment><USER2> From the abstract: "Using structure generation methods, we explore nucleic acid analogues within the formula ranges BC3–7H5–15O2–4 and BC3–6H5–15N1–2O0–4, where B is a recognition element (e.g., a nucleobase). Other restrictions included two obligatory points of attachment for inclusion into a linear polymer and substructures predicting chemical stability. These sets contain 86,007 (CHO) and 75,309 (CHNO) compositionally isomeric structures, representing 706,568 CHO and 454,422 CHNO stereoisomers, that diversely and densely occupy this space."

Damn, I was hoping for some non-carbon-based options :)</comment>


Tech Trust Index shows consumers trust Google and Amazon but not Sprint and AOL - <AUTHOR> http://survata.com/blog/tech-trust-index-shows-consumers-trust-google-and-amazon-but-not-sprint <comment><USER2> Trust as in trust what they're going to do with it. Google and Amazon are very up front about it. I trust I have a pretty good idea what they do with my data. And I'm pretty happy with it. Amazon knows I own a table saw capable of holding a 10 inch blade with a 5/8ths hole and I'm pretty happy with that and I sincerely hope they target some advertising for a nice 80 or more tooth plywood blade in my direction.

Apparently almost no one trusts snapchat to do what they claim. You delete this? Really? Somebody help me, do I have "gullible" sharpie'd on my forehead today? Maybe 90% of the population and I are wrong and they actually do what they claim, but...

Don't read it as "I trust you're doing the right thing" but "I trust them to do what they say they'll do".

</comment><comment><USER3> Stupid user anedote, but I am so infuriated with Sprint; Long story short: I went to Hong Kong and ran up several hundred in charges. When I got back, I hit some "spending limit" on my account and they shut me off.

I called, and found out it was due to the intl charges which were $366.12. I paid it off immediately, and then my account was reactivated.

My account was just cut-off again today.

I called to find-out WTF!!!

Turned out that they didnt use the 366.12 for the international charges - instead, they paid off my regular monthly bill and then left the intl charges as "past due" and when my next bill cycle came, it put me over that spending limit again!!

GOD DAMMIT!

</comment><comment><USER4> I'm surprised. After all the user rights and privacy issues pouring in this year - Google is most trusted. Perhaps, it's the lesser of evil.

If I were to choose from the list, it would be one single company - Mozilla.

</comment><comment><USER5> Although to be fair, the index doesn't really show that consumers trust Google and Amazon. It just shows that they trust Google and Amazon more than the others.

</comment><comment><USER6> It seems pretty obvious from this that consumers don't understand that when they are not paying for the product, they are the product themselves. It's also clear that this graph would look vastly different if given to a HN-only crowd.

<comment><USER7> Saying they "don't understand" is really condescending, especially given that "you are the product" sounds more like a political slogan than anything. It's more accurate to just call it a two-sided market.

Realistically, I think most people just don't care very much about targeted advertising.</comment></comment>


Ask HN: Does Spritz or Squirt.io cause hypnosis? - <AUTHOR>

Has anyone noticed themselves going into a hypnotic state (or a state of trance) when using Spritz or Squirt for more than, say, 15 minutes?
I've been using the bookmarklet from http://squirt.io/ since it appeared here on HN. Before today I had just been using it for relatively short blog posts and slightly longer news articles, but today I started out on a quest to read the whole New King James Version of the Bible in about 15 days at 950 WPM. (To filter out any distraction from outside my home office, I did this with some lyric-less trance music playing through my headphones.)
Well, about 24 chapters in I was noticed I was un-ignorably hungry, (I skipped breakfast this morning,) so I paused the bookmarklet and set out to grab some lunch at Chipotle, which is about a 10 minute drive from our house. I can't adequately describe the feeling or experience, (I tried, but it ended up being long and crazy-sounding enough that I felt a bit self-conscious about it,) but having been hypnotized years ago I can definitely associated the overall experience with that of being hypnotized. (For folks who code, I'd describe it as being in the zone twice over. :-))
Has anyone else experienced the same thing after using Spritz or Squirt for longer reading sessions? <comment><USER2> That is certainly a neat side-effect of concentrating awfully hard. I think I experienced similar things when taking standardized tests for college admission. Haven't experienced anything like that since.

I'm not sure that you're not a notch above the mean when it comes to concentration skills in the first place Andrew. :)</comment>


Bloom Filters for the Perplexed - <AUTHOR> https://sagi.io/2017/07/bloom-filters-for-the-perplexed/ <comment><USER2> Bloom filters are a nice data structure, and you should absolutely have them in your toolbox, but if you go looking for a reason to use one you are likely to wind up making things worse. The following is not valid reasoning: "Bloom filters are efficient. Therefore if I can find a way to use a bloom filter, my solution will be efficient."

The "SSH keys" protocol in the article seems like an example of this. It doesn't make any sense. Why would the server send the client a Bloom filter if the client has already told it what key it wants to check? The server only has to send one bit back to the client! And if the goal is to not trust the server with the client's (public) key, this protocol doesn't accomplish that either.

And if you do for some reason have to transmit the entire database of compromised SSH keys in a way that permits only membership tests, a Bloom filter isn't the most compact way to do it! For example, off the top of my head, you could calculate an (15+N)-bit hash for each element of the list, sort the hashes, and rice code the deltas. That would take very roughly 32768 * (N+2) bits and give about 1 in 2^N false positives. So for N=13 it is about the size of the bloom filter in the article but gives a false positive rate 8 times lower. This data structure isn't random access like a Bloom filter, but that doesn't matter for something you are sending over the network (which is always O(N)).

<comment><USER3> > The server only has to send one bit back to the client!

As much as the example is a bad one because it leaks server-side info to an unauthenticated client, I've had scenarios where if you have > 3 ssh keys in your key-chain all ssh login attempts fail after 3 keys are tried & cause failures. I end up writing ~/.ssh/config entries; a lot of them for the client to remember which key to try first.

My favourite real-life bloom-filter story is the "unsafe URLs" list that is in Chrome - the "Safe Browsing Bloom" is a neat way to send out obscured information about the bad URLs without actually handing out a list to a user. The web URLs or domains which find a match in this, do need to be checked upstream, but it avoids having to check for every single request with a central service.

On a similar note, been playing with a variant of bloom filters at work called a Bloom-1 filter [1] which works much faster than a regular bloom filter which has a lot of random memory access for 1 bit reads.

[1] - [https://github.com/prasanthj/bloomfilter/blob/master/core/sr...](https://github.com/prasanthj/bloomfilter/blob/master/core/src/main/java/com/github/prasanthj/bloomfilter/Bloom1Filter.java#L179)

</comment></comment><comment><USER4> When I first heard of Bloom filters, I thought of the Bloom effect - [https://en.wikipedia.org/wiki/Bloom_(shader_effect)](https://en.wikipedia.org/wiki/Bloom_\(shader_effect\)) \- and we used to call these things filters for a while - then friend of mine told me about the other meaning :)

<comment><USER5> I think the first thing any article about Bloom filters should mention is that they were invented by a guy named Burton Bloom. They don't have anything to do with "blooming" of any sort.

Very similar with Shellsort, which was designed by Donald Shell.

<comment><USER6> I always thought it was called shell sort because it invoked the image of a shell game and the pointer was like a shell covering the array element!!

Thanks for the edification!!!

</comment></comment></comment><comment><USER7> Some weeks ago someone posted a very useful interactive demo of a bloom filter (implemented in js) that you might want to play with after reading this article: [https://www.jasondavies.com/bloomfilter/](https://www.jasondavies.com/bloomfilter/)

</comment><comment><USER8> How does a Bloom filter with k hash functions hashing to a shared table of m bits compare to just using k hash functions each hashing into its own separate hash table of m/k bits?

<comment><USER9> Having many filters is worse, but not hugely so. I believe the problem is reducible to the fact that you'll have many smaller filters thus the random distribution hurts you a bit more.

The key word to google is "blocked bloom filter" e.g. as proposed in [http://algo2.iti.kit.edu/documents/cacheefficientbloomfilter...](http://algo2.iti.kit.edu/documents/cacheefficientbloomfilters- jea.pdf)

Here's a nice paper with some improvements [http://tfk.mit.edu/pdf/bloom.pdf](http://tfk.mit.edu/pdf/bloom.pdf)

We use blocked bloom filters for a couple of reasons, but one major benefit is the memory locality (our "bloom filter" is 32GB or larger, so it's handy & fast to be able to address it with separate "pages" which are really just individual bloom filters.)

</comment></comment><comment><USER10> Can anyone tell me about a use case in game design?

<comment><USER11> This link[0] has an example; so basically almost anything in a game where it has to lookup massive amounts of data (e.g. logs), the example in the article is to quickly check if the user has already seen an item (in a game with thousands of items [e.g because those were pseudo-randomly generated, think RPGs]). But it's easy to think further applications: quickly check if the player already played this chess game before (all pieces where in the same position) to make sure the enemy does something smarter this time (because that time the enemy lost), and such.

[0] [https://blog.demofox.org/2015/02/08/estimating-set- membershi...](https://blog.demofox.org/2015/02/08/estimating-set-membership- with-a-bloom-filter/)

<comment><USER12> It's not clear to me that the added complexity aka risk of bugs is worth it in your case for any reasonable game design.

In the chess example, knowing it's possible to lose from X positions is almost meaningless most of the time. The issue is search space sizes are either to large to be useful or small enough for brute force.

<comment><USER11> You can always use it things that are not critical for the game to work; and a good coder would make it in a separate class/container so most possible bugs are isolated as well.

In the chess example the most importan thing its not for the machine to win (or lose); is so the user feels its not the same game they already played; or -dare I say- think that the enemy is "learning"

<comment><USER12> Even cellphones can run chess programs powerful enough to beat any human. The normal way to tone them down is to make them more random which prevents games from repeating in the first place. Making this a non issue.

Even ignoring that and assuming you wanted to do a lookup vs all games played with someone that's a tiny dataset so looking it up has no real downside.

</comment></comment></comment></comment></comment><comment><USER13> Every month or so there is a new version of an article like this posted on hn

<comment><USER14> I read a few of these articles a couple of years ago. Along with a few of the inevitable cuckoo hash filter rejoinders.

I think they are neat algorithms and I'm glad to have come across them. But that said, I have yet to find a problem in my day to day work which required set membership, with space at a premium, and where false positives were acceptable. So I've never used either in anger.

<comment><USER15> If you are bored with bloom and cuckoo filters then check out quotient filters. Quotienting was one of those mind blown things for me.

<comment><USER10> Thanks for the reading list! :-)</comment></comment></comment></comment>


Lost In Translation - <AUTHOR> http://chriseidhof.tumblr.com/post/10161915672/lost-in-translation

<comment><USER2> I totally agree with this post (and the ability to convey such an idea in a few paragraphs is refreshing).

Basically, your mind is like a map of ideas created out of all of your experiences. Trying to describe a specific idea in that map with someone else is basically taking two different ideas and merging them. Both the describer and listen will end up changing their map: the idea.

Really hard stuff to do.

</comment><comment><USER3> I think a good way of stating this is that _no two people speak exactly the same language_. Even where simple terminology is concerned, everyone defines the boundaries of meaning in slightly different ways, and attaches their own particular connotations.

Most people will have the 'center' of their understanding of a given concept close enough to those of others' that the general case of communication is almost always satisfied. But in specific circumstances, as the need for precision in meaning increasingly presents itself, so too does the likelihood of an edge case in which understandings don't overlap.

With this in mind, a lot of the process of 'getting to know' someone can be construed as learning their language, in order to enable effective high- precision communication.

</comment><comment><USER4> Eric Evans' book _Domain Driven Design_ is all about this approach and is one of the best and deepest books about software design. (Disclosure: I worked with Eric for a few years. But that was because of my high opinion of his book and not the other way around.)

Finding an appropriate language/notation for a problem is perhaps the most important step in solving it. But it's also perhaps the hardest. Most software projects don't try. That's one reason most software is a mess.

</comment><comment><USER5> Sounds nice, but needs a concrete example to be meaningful.

<comment><USER2> I thought the example of using a DSL to get as close to the mindset of the customer as possible was a good concrete example.

I think it was also pointed out that even with this DSL, there was still communication errors. However, it seemed easier to fix the misunderstandings because there was a DSL there to fall back on.

<comment><USER5> > I thought the example of using a DSL to get as close to the mindset of the > customer as possible was a good concrete example.

No, "concrete" means that it's something real and tangible. Not just "a DSL" and "a customer", but "a language for the control of a nuclear power plant" and "General Electric" or something like that. Well, a specific company name is not so important, but the industry and what the language's scope was seem extremely relevant to me.

Without actually providing an example, you have no idea what level of abstraction they're working at, and what kinds of benefits and limitations the DSL may have.</comment></comment></comment>


German Infrared Night-Vision Devices WW2 - <AUTHOR> http://www.achtungpanzer.com/german-infrared-night-vision-devices-infrarot-scheinwerfer.htm <comment><USER2> [https://en.wikipedia.org/wiki/Zielger%C3%A4t_1229](https://en.wikipedia.org/wiki/Zielger%C3%A4t_1229)

<comment><USER3> I wonder why they put these on assault rifles rather than a high precision rifle - seems like an odd fit but I'm sure they knew what they were doing

<comment><USER4> I think the story of German WWII tactics and decisions on how to use novel technologies is that no they did not.

<comment><USER5> What are you talking about? The Germans surprised everyone with their mastery of novel technologies - it's how they took over the continent. This idea that they were hapless bozos when it came to capitalising on new tech is just plain weird. People look at novel tech like IR and say "ha, fools!" but for some reason ignore novel tech like stuka bombers.

<comment><USER2> They used their technology wrong.

Jet engines? Build a bomber!

Rockets? Instead of using the "Waterfall", a design on which all post-WW2 anti Aircraft missiles were based on to bring down enemy airplanes and bombers, they build the V2.

</comment></comment></comment></comment></comment><comment><USER6> The IR source is easy, but how whould they have done the imaging? All IR sensors I know are semiconductor based, clearly not a option at this time.

<comment><USER7> This is an interesting subject.

Lead Sulphide, according to: [http://antonirogalski.com/wp- content/uploads/2012/12/History...](http://antonirogalski.com/wp- content/uploads/2012/12/History-of-infrared-detectors.pdf)</comment></comment>


How to Hide the WhatsApp Last Seen Timestamp on your iOS and Android Devices - <AUTHOR> http://www.thegeekyglobe.com/how-to-hide-the-whatsapp-last-seen-timestamp-on-your-ios-and-android-devices.html

<comment><USER2> This is outdated advice. Whatsapp has since added the feature to their Android and Java apps. If you want to hide your last seen time just update your app to the latest version.

One interesting thing they've done is that if you hide your last seen time you can't see anyone elses either. Pretty clever on their part as it ensures that most people won't do it.

</comment><comment><USER3> I did it by use no any app. Just use airplane mode the read the message. After finish reading message, I turn off the airplane mode.</comment>