>To understands why Go is the way it is you need to know why it came to exist in the first place: "The goals of the Go project were to eliminate the slowness and clumsiness of software development at Google, and thereby to make the process more productive and scalable. The language was designed by and for people who write—and read and debug and maintain—large software systems. source"
The problem with this idea is that, for the exact same goals, there could be a much better design for the language and much better implementation of various details.
You don't need to be Haskell or anything. Just Go + generics for example would result in a much cleaner language (no special casing for things like "make" for example), a vastly improved code library and data structures story, etc. This horse has of course been beaten to death (including by people working extensively with Go, so it's not like some "outsider's misconception" as some dismiss it).
If Go succeeds is because noone else with the same kind of visibility and resources tried to compete in this space (easy concurrency, static builds, fast compiles, static, fast-ish, decent batteries included etc).
You have e.g. Rust which is incomplete and too complex, Nim which is too niche, from very small vendor (a guy) and has some bizarro ideas, and that's pretty much it. That said, Swift might make a dent in this area when its Open Sourced if it has nice tooling.
This was my favorite quote/sentence in the article. For me it feels extremely true. I am one of those people that has to write, read, debug and maintain large software systems.
Sure generic's would be nice, but I do not feel they really would change much. After using and supporting Go for years, I would rather keep it how it is. Simple and verbose.
Getting up at 3am in the morning to respond to a page going off in a production system that you didn't write, there is something extremely parseable with Go. It doesn't hide and abstract things in a way where you have to end up digging.
Often the docs are just not enough to really understand software. In the event you end up having to go read the code to understand it, when things get that far, I wish it was Go every time. There is little in the world more frustrating than having to read 18 java files to understand a simple format of a payload because your coming in late to the codebase.
How is Rust incomplete and too complex (especially "incomplete")?
Compiler-enforced-correct manual memory management may not be the right choice for every project, of course, but I think "too complex" is too strong of a way to say that. That implies there was a simpler way Rust could have achieved the same goals, and I've never seen anyone suggest one that works.
Surely the parent comment only meant that Rust was too complex to use, not that Rust was unduly complex. If Go would be a feasible choice, Rust is probably solving problems that aren't too relevant to you.
I think http://arewewebyet.com/ speaks to the completeness point sufficiently. Rust-the-language is probably complete enough for all but the most serious use-cases, but Rust-the-ecosystem isn't.
Twenty-two days after release, Rust started talking about making breaking changes (https://internals.rust-lang.org/t/pre-rfc-adjust-default-obj...). This conversation killed a Rust project I had pushed for... it played into all the existing negative ideas about Rust (constantly changing, not worth investing in) and gave the doubters all the ammo they needed to kill the project.
The change wasn't yet implemented, and had ZERO impact on our code-base even if implemented. But Rust-the-community seems too clueless on the importance of APPEARING stable and able to follow promises.
I wonder how many other Rust projects died because Rust-the-community appears like an untrustworthy ally (I am speaking of perception not reality).
The promise was "we won't break your code". The conversation was to determine the answer to the question "is there any code out there that this will break", because we take that compatibility promise seriously and want to honor it. If you're unhappy that we're having that discussion, well, I'm sorry, but we need to have these kinds of discussions if the compatibility promise is going to mean anything. The alternative would be to make these sorts of changes without discussion (or to stop making any kinds of changes that could break code at all, which rules out too many benign improvements; see below).
It's untenable to guarantee that, in a strict sense, the universe of all possible programs that run on 1.0 will always have the exact same behavior on 1.1. With any language, there are plenty of ways to break code in theory on upgrades that are very unlikely to lead to problems in practice; as an obvious example, incorrect unsafe code that depends on undefined behavior can break when the compiler starts optimizing based on that undefined behavior. I think that, instead, what we can realistically guarantee is that code that actually compiles in 1.0 compiles in 1.1. If there's no code out there that actually breaks, then I don't see any problem.
Golang has made many changes that could technically, and actually did, break code as well (just to name a recent example, the GOMAXPROCS default bump; there have been several others).
> If there's no code out there that actually breaks, then I don't see the problem.
Exactly, which was my point. Rust-the-community (and you as a member of it) see no problem with it... which for me, IS the problem. The timing, the fact that it played into all the existing narratives about why you never trust Rust, it made it a brutal bit of political weaponry in the hands of those who are pushing against Rust in organizations... and a bit of a kick in the junk to those of us who supported it. You saw it as without impact, when it has already had a huge impact on at least one organization.
> Golang has made many changes that could technically, and actually did, break code as well (just to name a recent example, the GOMAXPROCS default bump; there have been several others).
Rust isn't Go, that might seem "unfair" but that is the way it is. Go does not have the same reputation to fight against as Rust, the same famed history of breaking peoples code who are trying to use it, Rust WILL be held to a higher standard when it comes to breakage than ANY other language I suspect.
> Rust-the-community (and you as a member of it) see no problem with it... which for me, IS the problem. The timing, the fact that it played into all the existing narratives about why you never trust Rust, it made it a brutal bit of political weaponry in the hands of those who are pushing against Rust in organizations... and a bit of a kick in the junk to those of us who supported it.
Tell me what you wanted Rust to do instead. Again, the options seem to me to be either "make potentially-breaking changes silently without gathering feedback" or "make no changes to Rust that could break any code ever". If the latter, realize that this implies we could never add functions to modules (because of glob imports and shadowing), we could never add modules, we could never add trait implementations (because of method resolution), we could never add to the prelude, we could never upgrade LLVM (because of undefined behavior), and probably a whole host of other things I'm forgetting.
> Go does not have the same reputation to fight against as Rust, the same famed history of breaking peoples code who are trying to use it, Rust WILL be held to a higher standard when it comes to breakage than ANY other language I suspect.
I'm not sorry for doing so much development in the open instead of behind closed doors, even if everyone got to see how much the language changed from 0.1 to 1.0 and it acquired a reputation of "changes all the time". The point is, it doesn't change all the time now. From 0.6 to 0.7, for example, all code everywhere broke. Same with 0.7 to 0.8, 0.8 to 0.9, and 0.9 to 0.10 (though the amount of breakage got less over time, as you would expect). Conversely, the amount of breakage between 1.0 and 1.2 (assuming the trait lifetime change goes through) is so minuscule we don't even know of a single crate anywhere in existence that it would break. This is, in my view, so different as to be incomparable.
Well -- if we are going into what I would have preferred. I would have preferred a rest period after release. No ongoing changes across 3 trains on a 6 week cycle. Give the community time to accept, adapt, bitch, moan, whine, create workarounds, and then better workarounds. Let enterprises have time to buy in, test, accept or reject and give feedback. Deal with critical issues and focus on stability as a deliverable... and don't break anything during the rest period (even if that means being on a single version of LLVM and no new traits or modules or functions or whatever). But, that ship has sailed.
> I'm not sorry for doing so much development in the open instead of behind closed doors
Who asked you to be? I was simply pointing out the reality that Rust has a reputation to contend with -- you can't change that be being righteous about it, it just is.
You appear to have an expectation that the 1.0 release itself is an LTS release. I'm not sure where that expectation came from, but it is not correct. 1.0 is just the foundation for the language's stable evolution, and I don't expect any Rust code to linger on 1.0 in lieu of upgrading to 1.1.
The arrival of the 1.0 release also doesn't imply that the language is "done" or ready to use for anyone's particular use case (e.g. Servo is still on nightly, and will be for the foreseeable future). There are crucially important things that are currently being stabilized, and delaying those for an additional three release cycles would just be an arbitrary obstacle for those seeking to shift their code from nightly to stable.
We also don't need three release cycles to get feedback because we've been collecting feedback all throughout the 1.0-alpha and 1.0-beta cycles. Now would be the worst time to institute a freeze on API additions because of all the APIs that people are clamoring for but that didn't make it to stable for 1.0 (https://github.com/rust-lang/rust/issues/24028).
We're also working closely with several dozen companies using Rust to determine what development to prioritize (if you would like to add your company to this list, then please see the email address in my HN profile). As a result of this collaboration I expect to submit an RFC next week to propose that Rust 1.5 become the first LTS release, with subsequent LTS releases happening every at every fifth release. Do note that this idea is very preliminary (don't take it as gospel), but if accepted it would mean that we have until October 30 to stabilize any features that we want corporate users to be able to take advantage until the next LTS.
(As for that proposed "breaking change" that 1) wouldn't break any code in the wild, 2) would be trivially fixable with a lifetime annotation, and 3) could be opted out of with a single attribute, every company that I have asked about it has said that we should go through with it.)
> if you would like to add your company to this list...
Sadly, in the near term, the Rust boat has sailed. LTS releases would give a real good reason to reconsider if they ever come about. What support durations are you considering for LTS, and where can I read more?
I'm not sure of all the parameters yet, I'm coordinating with our corporate partners to see what they would find most useful. I'll be posting the RFC to the users forum and reddit once it's done. You can also give me your email address and I'll notify you when it's ready. :)
>Yes, there is more of a learning curve, but I think that's a problem with manual memory management in general. To me, that doesn't mean that the language is "too complex"; rather it means that the space Rust is playing in (and which those other languages are not playing in) is complex.
Yes, that's probably the case (Rust caters to more complex needs). Still makes it more difficult to just "dive into it" like you can with Go or Java or Python etc. Of course it's probably much simpler compared to mastering C++ or getting C right without dangerous bugs.
I agree with all of that. :) I don't think it does Rust any favors to pretend that manual memory management doesn't have cognitive overhead compared to pervasive GC, but at the same time, I don't think that it points to anything wrong with the language; "a safe, modern C++" is just a tough niche to fill, and I think (with the obligatory bias) that Rust did it well.
Not the parent, but I've read many comments here on HN from users who feel that if a language doesn't include an HTTP server in the standard library, it's not ready for production work. Ridiculous, of course, but that may be what the parent is referring to.
There's a funny story here about how Rails had to keep some patches around because Heroku users were accidentally using WEBrick in production because of defaults...
Well, it's a very common complaint (and I found it to be true when I tried my hand at Rust) that the lifetimes and general scope management can make your life hard -- and certainly harder than conventional GC languages. Rust, as a core language, has a lot more concepts to grok compared to Go or even Java.
As for incomplete, I mostly refered to the tooling and the available library ecosystem. Even Go lacks there, and Go is an order of magnitude better there than Rust. That said, despite the recent 1.0, the language is also heavily worked upon in several aspects (internals etc) and it doesn't seem that it's a "complete" offering that just happens to do incremental improvements, but a "we got an 1.0 out of the door, but we've got work to do to make it more mature".
> Well, it's a very common complaint (and I found it to be true when I tried my hand at Rust) that the lifetimes and general scope management can make your life hard -- and certainly harder than conventional GC languages.
Yes, there is more of a learning curve, but I think that's a problem with manual memory management in general. To me, that doesn't mean that the language is "too complex"; rather it means that the space Rust is playing in (and which those other languages are not playing in) is complex.
> As for incomplete, I mostly refered to the tooling and the available library ecosystem.
I've never found Rust lacking in tooling, with the notable exception of the lack of rustfmt (which is being worked on by Nick Cameron and others). I use native profilers and GDB with Rust almost every day, and Cargo is getting pretty mature. The library ecosystem isn't very mature yet, sure, but I wouldn't say that makes the language incomplete.
Rust is certainly harder to pick up than Go (and possibly Java), but I don't think that makes it any more complex than, say, C++.
The difference is in the learning curve. The concepts Rust forces down your throat are the same ones you'd need to learn in some way in C++ anyway (well, not the same concepts, but similar ones having to do with avoiding segfaults). The difference is that you can write simple programs in C++ whilst blissfully unaware of the perils that come later. On the other hand you sometimes need to understand ownership for even the simplest programs.
But for a larger application, you have the same amount of learning required if you want to responsibly write an app in C++ or in Rust.
When we're talking about using a language for something other than teaching programming newbies, we really don't care about small prime number programs being harder in Rust. We care about how hard it is to write large applications, and I strongly suspect Rust isn't harder than C++ for this.
Oh, by the way, for the most part lifetimes work themselves out[1] without effort from your side. And if you find them complicated, you can always compose the relevant wrapper object (like Rc for refcounted memory management -- almost a GC) and use it. It's a bit more verbose, but it's not hard to grok.
> the lifetimes and general scope management can make your life hard -- and certainly harder than conventional GC languages.
Except you have to solve those very same problems on your own with every other type of resource that is not called "memory" in other languages.
Ownership is a huge problem, having built in primitives to handle it is a benefit. Having or not having GC is almost (but not quite!) a separate discussion.
It's rather that Rust's standard library and third party library support is incomplete. E.g.:
- last time I checked there was no option to have non-blocking IO which is a pain.
- custom JSON serialization/deserialization from/into custom data structures is extremely painful (for reference, rustc_serialize's Decodable trait).
- thread::scoped leaking destructors under certain conditions. This is more of an example of how a complex language gives rise to complex issues that very are difficult to debug and fix.
This will get better in time obviously but this is the current state of the language. Nonblocking IO in particular is really unfortunate to see in a 1.0 version tag.
There are mio and serde respectively for your first two points, and mio in particular is really popular.
Regarding thread::scoped, I think that kind of issue isn't unique to Rust (Java, a language with a simpler memory model, has had all kinds of weird corner case bugs, especially around memory and concurrency). It's also, again, more an issue of "safe manual memory management is hard": the simple ways to avoid that issue would have been "GC everything", "sacrifice memory safety", or "remove reference counted smart pointers", which contradict Rust's goals.
The leakapocalypse is rather blown-up - I don't think you could observe it unintentionally. Besides, `thread::scoped` is something no other mainstream-imperative language tries to offer - parallelism with essentially no risk of race conditions.
> thread::scoped leaking destructors under certain conditions.
Note that this problem is one that has no analogue in other languages.
In most languages, including Rust, you can already "leak" things by putting them into a static hashmap and forgetting about it or sending them to a blocked thread or whatever.
Rust is unique in that it can demarcate types which are bound to a scope. Which gives the auxiliary guarantee that the object would be destroyed in that scope regardless of what happens next (because such objects cannot be returned from the scope or placed into a global hashmap or whatever). There is no analogue for this in other languages. Rust is not "incomplete" for not having this.
The current scoped API depended on this guarantee, but it turns out that there are convoluted ways to bypass the guarantee (so it's not a real guarantee). There's a new design that's been proposed which doesn't need this guarantee.
non-blocking io can be done via mio, and I think using serde for json is easier.
The problem with all statements regarding programming languages is that they rarely have empirical evidence to back them up. Do you have any data showing that generics will lead to a cleaner language? I have seen a study or two that tried to measure productivity, bug counts, etc with regards to generics and what it showed was that writing code using a library that is built with generics was ever so slightly faster. However, it showed that creating or editing a library that used generics took 10x longer.
It seems that you can't really make the claim that adding generics leads to a "much cleaner language".
The problem with this idea is that, for the exact same goals, there could be a much better design for the language and much better implementation of various details.
You don't need to be Haskell or anything. Just Go + generics for example would result in a much cleaner language (no special casing for things like "make" for example), a vastly improved code library and data structures story, etc. This horse has of course been beaten to death (including by people working extensively with Go, so it's not like some "outsider's misconception" as some dismiss it).
If Go succeeds is because noone else with the same kind of visibility and resources tried to compete in this space (easy concurrency, static builds, fast compiles, static, fast-ish, decent batteries included etc).
You have e.g. Rust which is incomplete and too complex, Nim which is too niche, from very small vendor (a guy) and has some bizarro ideas, and that's pretty much it. That said, Swift might make a dent in this area when its Open Sourced if it has nice tooling.