> It’s unprecedented for a language to be both garbage-collected and as squarely aimed at systems programming as Go is, because systems programmers have trouble tolerating the stop-the-world pauses that happen when the GC runs.
Only for those that never heard of Mesa/Cedar, Algol-68, CPL, Ada, Modula-2+, Modula-3, Oberon, Oberon-2, Active Oberon, Component Pascal, Oberon-07, C+@, Sing#, System C#, D.
Interestingly, one of the Go core creators, Robert Griesemer did work at the ETHZ and seemed to have gotten a proper dosis of the Wirth languages which then strongly shaped Go.
Software development has eternal amnesia. Deep understanding of the pros and cons of different ways of structuring things are being continuously re-learnt with each passing fad, and each rewrite of a legacy system by a bright new crop of young things who learned most of what they know with a decade or so of direct experience.
Different concerns have different emphases in each fad, but the systems built have structural isomorphisms with what came before - they could hardly avoid it, being built to solve the same problems - and the older experience is lost, because people focus on the surface, rather than the larger shape. Older experience is dismissed because it was in an outdated language, despite it containing lessons that will continue to be applicable.
Everyone is myopic. It's like politics; the appearance of things is what matters. It's like fashion; it's the intersection of the ideas associated with the surface structure of your output that define its perception. No wonder older developers tend to leave this industry.
> You want to make your way in the CS field? Simple. Calculate rough time of amnesia (hell, 10 years is plenty, probably 10 months is plenty), go to the dusty archives, dig out something fun, and go for it. It's worked for many people, and it can work for you. - Ron Minnich
But if you could learn some things from the history and use that to your advantage, why wouldn't you? Everyone would be doing so. And yet somehow it doesn't work like that, outdated things are in fact outdated and you can only take away very little from them. Things that were designed with trade offs for very expensive slow synchronous machines during the times when programmers were not bound to languages, because everyone had to develop everything from scratch, don't really make much sense today. Direct experience of the last decade is a lot more relevant with a lot more lessons to learn that were never even on the radar in the past.
> But if you could learn some things from the history and use that to your advantage, why wouldn't you? Everyone would be doing so.
Hah! Reasons for not learning from history:
* history is hidden behind NDAs, bad licences and patents
* history is hard to access due to its environment (printed on out-of-print books, stored on tapes, HDD and other forms of storage in someone's basement)
* history is written in a programming language nobody knows anymore
* history is written in an incompatible programming language, one for which there are no stable bindings to your favorite language (or for which there aren't any bindings, period)... just think how many times the String class or data type has been written and rewritten just in something like C, let alone the copies in Java, PHP, Ruby, Javascript, Go, Rust, etc., etc.
There's a ton of (somewhat) valid reasons history is forgotten and most of them aren't "history was bad, let's just forget it".
True, but many of those hurdles are easy to overcome when one is curious about history of computing, specially since many libraries have been scanning old books and papers.
For example, I have collected the majority of Xerox and DEC research papers that I could get hold of.
There's a variety of reasons. It's often because our languages are too low-level and the architecture too opaque, such that you need to study a codebase for a long time to understand what works well and what doesn't work so well. The hill you need to climb to reach an epiphany is sufficiently steep that people much rather build their own hill, and learn their own lessons.
The trade-offs come around and around, the lessons are not as inapplicable as you think. We used to struggle to run programs on small machines; those struggles came back again with mobile, and come back again in a slightly different guise in clusters (where the program is too big to fit on any one machine).
They recur on different scales, too. Just the other day I was looking at dependency injection. Dependency injection solves the problem of coordinating dynamic program composition; the reason the program needs to be composed is because it was decomposed for testing. But this is just another iteration of the same pattern come around again. It's been done before in a large variety of ways; sometimes through ambient configuration (global variables), sometimes with patched jump tables (dynamic linking), sometimes statically (module instantiation). The emphasis is different - testing - but the solution is not structurally novel in the least.
> Direct experience of the last decade is a lot more relevant with a lot more lessons to learn that were never even on the radar in the past.
Do you make that statement with the experience to back it up? Or do you make it because "if it were useful someone would have done it"? What if everyone is thinking the same thing as you are?
Beyond what other people have said, we are also a relatively young industry. There aren't that many people with 30, 40 years experience in the field. When I got my CS degree, 13 years ago now, there was no such thing as a "software engineering" degree, and CS was mostly focused on CS rather than the sort of thing you're talking about.
I also wonder how much collective knowledge we throw away with pushing developers into management. Or the outsourcing in the late 90's and early 00's. Or ageism. We are purposefully driving people with knowledge out of the industry.
>"As the OP was kind of insinuating just because many are too young to remember the OSes written in those languages, they should be ignored."
No, I wasn't. It was an honest question.
The only OSes I've used or had any experience with are Dos/Windows, MacOS, iOS, various Unix/Linuxes and the reaally old Commodores/Macs that just ran Basic. I was hoping maybe something I'd heard of wasn't based on C/C++.
Faire enough, so prepare for an history lesson. :)
Mesa/Cedar was created at Xerox PARC, as an extension of the Xerox Star 8010 system, which was programmed in Mesa, the language that inspired Niklaus Wirth to create Modula-2.
https://www.youtube.com/watch?v=ODZBL80JPqw
Mesa evolved to Mesa/Cedar, which allowed for automatic memory management via reference counting and a tracing collector for the cycles.
It had a strange mix of UI, using a mix of text and mouse input. Basically all applications were dynamic modules and the procedures/functions with a special signature could be used from the UI.
So you could select text or objects from applications, and invoke such operations on the selection.
The Oberon System 3 and Oberon V4 with their Gadgets framework were the best experience, before AOS was designed.
I continue to be surprised by the sheer amount of writing we see about ntpsec. The project was started over two years ago, and yet progress reports seem very optimistic and self-congratulatory, despite an obvious lack of progress.
Sure rewriting "bits" of things, with more features, and adding my python sounds useful. But here we are 500+ days since the project started and there are only minor experiments in moving from C.
I get the feeling this is one of those projects which will never be complete. Perhaps not a bad thing, providing those involved are having fun, but so much verbiage to say so.
What progress are you looking for? There seem to be downloads here, posted pretty regularly: ftp://ftp.ntpsec.org/pub/releases/
I don't know if they build and work, but I'd suspect they do, based on the refactorings being discussed. The commits seem to be clicking along. A diffstat of roughly where I think they branched off of ntp vs. master takes a moment to poke through, because the raw stats are "1032 files changed, 126489 insertions(+), 143789 deletions(-)", but there's a lot of trading C code for test code and more docs in there.
I don't know exactly what metric you're using but this doesn't match my "obvious lack of progress".
They started with Mills ntpd, so there have been downloads available since t0. There's a significant amount of code you can lose from a large C project just by getting rid of ifdefs that nobody uses, so the +/- line count isn't a great metric either.
The true metric for success for something like ntpsec is the number of meaningful security problems ntpd has been vulnerable to since ntpsec's inception that ntpsec hasn't been.
At the point where they rewrite in a new language, they're embarking on a fundamentally different project with a different value proposition, which sort of moots the progress they've made (or not made) on hardening ntpd.
(Fair warning: I am both an ESR skeptic and an ntpsec skeptic; I genuinely do not like the idea behind the ntpsec project).
> The true metric for success for something like ntpsec is the number of meaningful security problems ntpd has been vulnerable to since ntpsec's inception that ntpsec hasn't been.
They talk about 3 areas where bugs have been removed, including:
Much of ntpd’s most convoluted code lives in ntp_proto.c, which
implements the state machine central to the protocol. Of the 29
vulnerabilities that have received CVEs so far in 2016, a couple
of multi-KLOC functions in ntp_proto.c are responsible for 15 of
them — just over half. Of course, "just rip it out" wouldn’t
suffice in this case: this is core business logic, not junk code.
So we rewrote those functions from scratch, cutting line count
considerably and yielding a far more readable result.
From this paragraph you might get the impression that ntpsec had dodged 29 CVEs in 2016. But that's not the impression I have: I think it has been vulnerable to many of the bugs reported in ntpd.
Further: not all CVEs are equivalent, so in addition to wanting to know how many vulnerabilities ntpsec was also vulnerable to, you also want to know what the distribution both of severity and of exposure in the default configuration those bugs had.
Ultimately: I feel about ntpsec the way I would have felt if, in 1997, someone had proposed SendmailSec. The answer to the Sendmail security problem wasn't a "hardened" Sendmail (though the Sendmail team sure tried); it was Postfix and qmail.
> There's a significant amount of code you can lose from a large C project just by getting rid of ifdefs that nobody uses, so the +/- line count isn't a great metric either.
Can't 'ifdefs that nobody uses' hide security flaws? Removing them helps the overall security of the codebase, preventing folks from accidentally enabling a long-dormant codepath, no?
> The true metric for success for something like ntpsec is the number of meaningful security problems ntpd has been vulnerable to since ntpsec's inception that ntpsec hasn't been.
I'm not saying that eliminating unused compile time options is a bad thing, just pointing out that the real security improvements from hardening something like ntpd come from simplifying and eliminating code that is in the default compile that everyone uses.
Really all I'm saying is that you can't get a reliable metric of progress on something like this from a simple line count.
> I genuinely do not like the idea behind the ntpsec project
I don't know the NTP protocol well enough right now, or the aims for the ntpsec project itself. I will say that having a signed response from an NTP server, would raise the trust level of the accuracy of that response. That is, no one can respond with a bogus time and screw up all sorts of stuff.
In terms of privacy/tls etc, that seems less important. But signed messages would be good.
ntpsec isn't a project to revamp or cryptographically improve the NTP protocol; it's an attempt to do for ntpd what BoringSSL and LibreSSL are doing for OpenSSL.
What you really mean to say there is that Franke is heavily involved both in ntpsec and in modernizing NTP protocol security. :) But the two projects are unrelated. I'm also interested in (and more optimistic about) things like AGL's roughtime:
... but I acknowledge being somewhat mystified by how much complexity is in NTP given the very minimal needs virtually everyone I've ever worked with had for time synchronization. We all need it, but we don't need it to be ntpd-grade featureful. So this is probably a blind spot for me, and maybe roughtime is less promising than NTS.
Downloads have always been available, as this project was started by taking an existing one - then trying to cut down on things that were insecure, bad, outdated, or similar.
In short this project is very like the forked openssl project. Progress has been made, I can see it, but I think taking two years to turn some existing code into something cleaner is .. surprising.
Especially now that the focus seems to be throwing it away, and starting anew in rust / go (though based on recent updates go seems to be the choice).
Moreover, at the point where you're rewriting ntpd in a new language, you're no longer really producing a hardened version of the original. There already are competing ntpd implementations, if that's all you're after, so this latest excursion into Rust and Go raises the question of whether the project still even makes sense.
I've been pondering this question too. NTP is a very important Internet service and it's great that folks are looking for a more secure alternative to traditional ntpd. I'm not sure if NTPsec is going to get there or not.
The best alternative out there right now seems to be Chrony. But it hasn't had nearly the inspection and usage ntpd has had, so it's hard to know for sure about its security. ntimed was also looking promising but seems stalled. openntpd doesn't keep time very well and systemd-timesyncd isn't really an NTP implementation.
I had the same thought. I will say that that lack of progress may be the exact reason why so much consideration is being put into porting to another language, so as to make faster progress.
> I checked this by writing loccount as a parallelized tree traversal. Each file in the tree gets a goroutine spawned to count its lines; the threads run in parallel and as each finishes its work it stuffs a statistics block into a channel.
In the past, this approach would blow up because Go would spawn a kernel thread for each blocking system call that was performed. I had to use a rate limiting channel to constrain the number of kernel threads. Is that still the state of affairs?
Yes, that is still the case. Cgo calls work the same. Note that the most common syscalls get special treatment though: file and network I/O use a thread pool and epoll/kqueue respectively.
Isnt there a way to limit the number of threads? Starting N threads each reads the same queue and executes the operation. The queue gets full when there are no workers are available. I though you can implement something like this in Go...
"I think writing toy programs - conscious finger exercises - are a terrible way to learn a new language."
whoa hold on there. everyone's learning style is different. Doing "dumb simple" things first and extracting reward from it is essential to growing progress, even for advanced programmers imo.
For me, the "learning curve" of Go was very small and that's the kicker. You can get up to speed quickly and get a 'feel' for the language quickly. It's been a great learning experience and I recommend it thoroughly.
I continue to be surprised by this argument. It seems to only matter if your job is to learn one language per week.
I don't need to get up to speed in a weekend. It's the speed that I'm getting up to that matters. Of course there is a limit to this principle, I grant you that.
What matters as well is how readable other people's code is, or even my own code after not touching it for a year. And I mean readable for someone as proficient in the language as the original author. This aspect sometimes seems underappreciated by proponents of "powerful/expressive" languages.
Learning curve is important because it means you can bring a new team member up to speed quickly--you don't need to find Go developers, you can make them. The learning investment will pay dividends very quickly. Also, Go can be mastered in 1-3 months, whereas other languages take years. Being able to quickly (i.e., cheaply) produce experts in the language seems advantageous.
I think what you are saying is that the readability of a language is more important than how easy a language is to learn. I heartily agree. Languages that encourage simple, readable code trump pretty much any other language out there, in my opinion. I can't tell you how many times I've looked at my overly abstract Ruby code and just thought, WTF?!
I like Go for this reason. It has more noise (err) than I'd like, but when I look at most Go code, I find it relatively easy to follow and modify. There's no other language I've used that achieves this so consistently.
That is the beauty of gofmt in my opinion. You can pretty much guarantee that your code will be almost the same style as someone else's code. Which in turn increases readability down the line for someone who knows the language.
I encourage anyone that hasn't learned Go, to do it as well. In fact, everyone should learn as many languages as they have time for! Each one has interesting decisions they've made that will possibly help you in your everyday language of choice/work.
That being said, Go was fun to learn, and taught me that deployment does have to be as painful as it's been in Java for so many years. But I encourage people to also spend some time with Rust, as it has made a very different set of choices. For me the type and generics system are the best I've ever used and I wish I had access to them in Java.
>It’s nice to see CSP in a language I can use for production, and very gratifying to find that it really is an effective tool for carving up concurrency problems. If there is one pitch the Go designers have knocked right out of the park, this is it. I’m already sure I’m going to miss it a lot in Rust.
Wait until he realizes that Rust has channels, too. It's not as pure as Go's implementation, but it's a superset.
So I have to wonder about the performance difference between his sloccount and loc (https://github.com/cgag/loc) which is so fast it always makes me think that it hasn't done anything (same as ripgrep).
I'm like 98% sure loc will be faster, but it would be interesting to know by how much.
Because they kind of are, even though they are targeted to different set of skilled developers and Go happens to be a bit spartan in features.
For any type of application, including user space drivers, that can be developed with the constraints of a sub-millisecond GC pauses, GC is a good language, in spite of its stance on generics.
As for kernel space, Go could eventually be used as well, in spite of GC hate, as academia including Microsoft have proven a few times.
Me personally, I prefer Rust, but I do see others would think otherwise.
- Both were invented by a major browser vendor, roughly around the same time.
- Both include an unsafe fun zone that lets you play with raw pointers.
Maybe some of that was inevitable just by following the trends in the field (safety and parallelism in particular), and we'll see other new languages making the same choices?
Safety is hardly a trend is it? GC'ing everything makes safety rather much easier. Go doesn't go beyond Java level safety or really any of many earlier "managed" languages. Does Go offer safety above, say, PHP?
Rust not only does all that, it provides data race safety, and does so without a runtime or tracing garbage collector or real performance sacrifices. All while maintaining C linkage for zero cost interop. I can use Rust basically anywhere I could use C, Go, not so much.
That seems to put it squarely in a different segment than Go.
Mostly. Java puts a lock on every single object in a multithreaded context; Go doesn't do this as a performance tradeoff, so two goroutines manipulating a pointer simultaneously will likely corrupt it. FWIW, I've been using Go for 4 years and I've not yet seen a memory corruption.
No they're not. Go is very easy to pick up, Rust is not. That point alone should be enough. Without prior knowledge of both, no sane person would consider writing a browser-engine in Go, and yet that's exactly what they're doing with Rust. Just as no sane person would pick up Rust to write generic web services in that scenario.
Put Rust and Go in front of a python coder who wrote dozens of web services using flask - and I am pretty sure I can predict what tool he'll pick. Sure you could write web services in Rust, that's not what I'm arguing, learning Rust for writing stuff like that is simply not worth it for people having to write such services.
Rust's complexity is comparable with C++, and the main reason for this complexity is to address problems that are mainly seen in C/C++ applications. Rust's reason for existing is simple: modern low-level language with built-in (memory) safety with no performance trade-offs (implying concurrency support etc). That makes it squarely aimed at C++, where developers accept the complexity as a trade-off for performance.
Go's reason of existence and goals are completely different, it addresses the gap that existed between compiled and interpreted languages. It wants to be a simple, safe, easy to deploy language that offers more performance over classic scripting languages and thus is able to address more performance-critical issues. It's main target is clear: servers and networking services, where a GC's impact less important due to the I/O bottlenecks in most scenario's.
Of course, there's a lot of double-talk on the subject. "You can TOTALLY do it today!" ... "Eh, but maybe you wouldn't want to use it PRODUCTION today" ... "But we're just a FEW more crates away from being there!"", etc. The Rust community is great, but they seem they hedge their bets too much and are murky with the messaging.
Right or wrong, Rust and Go compete because there are a LOT of web and microservice developers out there (including me) who:
1. Love what Go brings to the table in terms of of type safety, and AOT compilation to single-file native executables...
2. ... but wish that Go had more functional-style constructs (filter, map, immutability, etc), generics, a contemporary package system that doesn't involve putting Git URL's in your actual source code... or any of Rob Pike's other stubborn alien quirks that people don't like.
Rust can't quite figure out whether it wants to market to this crowd or not. Sadly, due its learning curve, I DON'T believe that Rust is the answer for the "Go, but with more popular features" problem. But enough people aren't ready to concede that yet.
Rust absolutely does want to market to the web services crowd. They said as much during their year-end conference. The whole push with futures is partly because of that. This year you'll see a lot more development in the web arena. I realise this messaging is probably what you've heard already, but I believe when futures are integrated into the backend frameworks you'll see some really competitive offerings.
The question of Go or Rust for something like web services is not as clear cut in my opinion. I have JavaScript/PHP background, and have recently learnt Rust for just this use case. Rust is slightly more complex (but really not that much, nothing close to as bad as C++), but also offers more correctness guarantees. Both are good choices, hence these discussions.
Long time C++ developer here, have written a few toy programs in Rust, and am in the process of re-writing some stuff at work in Rust (from python).
My opinion is that Rust is at least as complicated as C++. They have different complexities, but one isn't "easier" than the other. I enjoy Rust a lot. More than C++, at this point, but that may be the "newness" factor creating bias. I think Rust is likely a better language for people new to systems programming to pick up. It's complexities are largely up-front: a novice will learn how to program well in Rust by having the compiler break his teeth a few times, while for C++ she'd either have to have high-quality mentoring or else learn the hard way (by long experience).
Even if Rust were as complicated as C++, with its ridiculous number of interacting features and backwards compatibility constraints, it manifests very differently: the Rust compiler keeps track of the complexity and tells you when things go wrong, while the programmer has to do pretty much all of this manually in C++. Many of the constraints Rust requires are constraints that people often try to do manually in C++ (e.g. avoiding dangling references and use-after-move), hoping that they get it correct.
> but really not that much, nothing close to as bad as C++
C++ dev here. Rust's borrow checking system is crazy and even after a week of trying I couldn't understand it in a way that I could reliably use the language.
In C++ everything is fairly straight forward and well documented, in Rust it feels like I'm inserting random symbols in hopes that something will compile. The syntax is verbose and ugly, maybe not as bad as C++ template code can get sometimes, but it's nasty in its own right.
I want to like Rust, I really do, but this just really turned me off it.
This is a rosy-eyed view of C++ if I ever saw one. C++ has a lot of accidental complexity from layers and layers of features and backwards compatibility concerns: maybe some of the features are "straight forward" in isolation, but its interactions with the rest of the language rarely are.
C++ is deceptive, in that the compiler barely keeps track of anything for the programmer, so there are many cases when code should have "random symbols" (or something equivalent) added, but isn't, just being broken instead. The Rust compiler front-loads this: trying to turn runtime brokenness into compile-time errors, which does make it annoying to get code that runs, but it makes it less annoying to get code that actually works correctly.
> In C++ everything is fairly straight forward and well documented
Wow! C++ is full of undocumented and documented, but non-obvious, behavior. I guess that speaks volumes about your experience with C++: given enough time, anything is straightforward.
Rust has a steep learning curve (I'm still climbing it), but it is nowhere even close to C++. C++ gives you a false sense of security, in the sense that code will often compile, but be obviously wrong (for someone knowledgeable). The Rust compiler will not stop complaining until you correct your program.
It's even worse for beginners. Rust learners will get frustrated because their programs are not compiling. C++ learners will get frustrated because their programs will segfault. Often because of some obscure issue, such as someone who forgot to implement copy constructors or assignment operators. I've been there, these issues are completely non-trivial to debug.
I would rather have a compiler yelling at me, but that's me.
Also, since you mentioned that you've been trying for a week: do you think a novice C++ programmer would be able to actually do anything coherent in C++ after a week? Heck, I don't think that's enough time to even go through the spec!
I as Java developer had some hurdles, but most of the time, me and borrow checker get along. My greatest improvement came from compiler lifetime elison in one of the pre-1.0 versions of Rust.
As for syntax being ugly, I do somewhat agree, but mostly, when it reminds me of C++ (e.g. T<U<Vec<u8>>>). I hate tire-tracks and Type::static_method() definitions.
JS/Php dev here as well, I've been learning Rust for some weeks now and it is hard for me. I've never really done any C/C++ (only Java in my school) so a lot of concept are quite new.
I'm currently working on an API wrapper in Rust to improve myself, it's been a week already and I'm still working on it whereas I could have done it in 30mn in JS.
'Put Rust and Go in front of a python coder who wrote dozens of web services using flask - and I am pretty sure I can predict what tool he'll pick'
It depends what part you show. For example Rust has an experimental flask/sinatra/... inspired library (https://rocket.rs/overview/), and although Go has similar things you can't cut boilerplate that much:
So in the end it may depend why someone likes python in the first place: because of the concise high level constructs or because of ease of use.
I have a dream that one day rustc will be able to output go-mangled-symbols with lifetimes integrating into the Go GC. My dream is that we can flesh out a project in Go for good performance and then extend it in Rust without stack swapping. Then we can bash out projects in Go and still have face melting performance with zero overhead abstractions. Go and Rust should be besties!
"Rust competes for mindshare with C++ and D for programmers who are prepared to accept more complex syntax and semantics (and presumably higher readability costs) in return for the maximum possible performance. For example, micro controllers, AAA game engines, and web rendering engines."
"Go competes for mindshare in the post 2006 Internet 2.0 generation of companies who have outgrown languages like Ruby, Python, and Node.js (v8) and have lost patience with the high deployment costs of JVM based languages."
With a sub-millisecond GC pauses there are many overlapping use cases.
For example, while you might need Rust to target a PIC or a ESP-32 class processor, Go will run perfectly fine on a ARM Cortex-M3 which also has hardware vendors selling Java compilers, e.g. MicroEJ OS (http://www.microej.com/).
GC pause time is not the only criterion, and focusing on it to the exclusion of all else is problematic.
I used to have to explain this in a HN comment every time it came up, but now Mike Hearn has written up [1] better than I ever could, so I can just link there :)
I agree, but still Go can be usable in quite a few scenarios.
Sure it has quite a spartan type system and I would rather use something else for my own work.
On the other hand, as an ex-Oberon user I am aware of many use cases that Go can easily fulfil and like to make people aware of it, more Go less C is good.
There are many things that are not AAA games, browser engines and micro controllers where C++ is used and where the Rust community would like Rust to be used.
Rust and Go might compete in that area, assuming that Go programmers will have interest in such projects.
It's not in the interest of the leaders of each community to admit that though.
I had the exact same thought. On top of that, the fact that he did this before the post on Rust is strange. Why publish them out of order? Reading this first would have made it clear that he already had a strong bias towards Go, and also would have showed the Rust community what it was in detail that he liked in Go, so as not to have inflamed so many who love Rust.
It seems at this point clear to me, that the previous Rust piece was written out of sheer frustration, and that the entire period while "learning" Rust he really wanted to be writing in Go, which he had already found to enjoy. This is understandable, but creates a clear bias; which is completely fine, but would have been nicer to see this for that reason.
Everyone's experiences are going to lead them in different directions. I learned Go, decided it was missing features that I really wanted, and that's when I decided to learn Rust. That was a decision driven as much from comfort with a language as it was technical. Which brings me back to his original Rust post, it was written as though comparing two languages on their technical merit, when in reality (after reading this post) it was really about comfort. Again this is fine, and would have been clearer if posted in the original order.
I've changed my main language for doing work only a handful of times and it usually takes a few years of doing side-projects in a new language before I switch.
For instance it took about 7-8 years before I switched to Java (and then only after establishing a programming style that doesn't rely on frameworks at all). The language wasn't hard to learn, but it took a while for the JVM and the standard library to get to where it needed to be.
C++ never made the cut. Quite possibly because C++ is not really one language. There were at least as many styles of C++ as there had been projects I worked on (except perhaps at Google, which is the only place I've worked where I've consistently seen good quality C++ code).
I'm in the process of evaluating Go as my main language and I have to say that this is the fastest I have gotten comfortable with a new language. I've been noodling around for a few months, doing side-projects, but my experiences so far have been very positive. Unlike most languages I haven't come across any uncomfortable stuff that would be hard to overcome. Just the usual confusion about what the idiomatic ways to do things are.
What is striking is that it is equally comfortable for doing relatively low-level (my first Go program talked to a chipset over SPI on RPi, doing something that is slightly timing sensitive) stuff and stuff that needs you to build abstractions.
I haven't used Rust yet. Mostly because I don't have the time. And I chose Go since some of my friends use it for software that you and I touch every day, thus providing me with access to people who have used it "for real".
Go just might be my next "main language". (Actually, right now it feels like I'll switch to it and never go back, but the tiny rational bit of my brain says "oh yeah, here's a list of other times you had a good feeling about something that turned to crap" :-))
Sorry if you saw this coming but do you really not miss generics and exceptions? I like Go given that it's a lean language and the compiles down to a self contained binary which doesn't consume gobs of CPU or memory and is pretty quick to start-up and run. Perfect language for writing command line tools and one-off network clients.
But I dread the feeling of writing repetitive error handling code and copy-pasta to get a simple generic functionality to work across data types. Maybe I should just consider it a better C and move on...
I haven't wrapped my head around how I want to do error handling in Go yet, so it is a bit early to say. I think I really need to write more code that deals with abstraction layers before I can have a useful opinion on the matter. Not that I'm too worried about not having figured out that bit yet since error handling took me a while in all other languages as well. (I think my first approach was to use panic() where I used exceptions in Java. But that doesn't really tell you anything very useful unless you also know how I use exceptions in Java :-))
I don't mind a bit of boilerplate as long as it produces understandable code. Writing boilerplate can be automated. Reading and understanding code can't.
I do understand where you are coming from though. Perhaps we're getting a bit spoilt as programmers in feeling that error handling should be ... more elegant for a language designed within the last decade? :-)
I think the same goes for generics, though I have a hunch that I'm not going to miss it. And I'm not sure why, but that's how it feels now. Whenever I do design classes that are genericized in Java I do so sparingly. This is mostly to ensure that the code is easy to reason about. I'm not fond of "clever" uses of generics because while it may feel satisfactory to have things click together in a beautifully complex manner, it can make code hard to read.
DNS lookup stalls as motivating concurrency .. messy, complicated code with known bugs .. seriously? It's not that hard to call getaddrinfo() in a thread and feed results back (atomically) over a pipe. No shared memory or mutexes needed.
Looking at Android as a representative of "embedded" also seems a bit fallacious. The lowest-end android device I can buy has a lot more ram, storage and clocks than an average home router.
EDIT: this comes across pretty snarky - more so than is warranted. I'm surprised by the first part, but have no right to impugn the whole project based on that. The surprise remains, but I apologise for my tone.
> Looking at Android as a representative of "embedded" also seems a bit fallacious. The lowest-end android device I can buy has a lot more ram, storage and clocks than an average home router.
Well you can look at ARM Cortex-M3 running MicroEJ instead.
MicroEJ OS, a Java based OS for micro-controlers like the ARM Cortex-M3, with 128 MB NAND FLASH + 512 kB internal for storage and 32 MB SDRAM + 96 KB internal for program data, running at 12 MHz is far away from the average Android device configuration, yet can still run a mix of Java/C stack.
DNS gets so much blame, and yet so little time is spent to make it better. If DNS is that important to your application, you should install a caching resolver locally on your system.
Depends on the situation, if you are in a server that needs to handle millions of requests and you create a million thread probably wont fly. If your concurrency is limited to a low enough number than you can create and terminate threads, so the proposed threading solution works well on mobile devices.
I don't think he was complaining about the lack of a syntactic token reading "const", but rather the inability to protect values from modification (in certain contexts) without incurring the overhead of hiding them behind an interface.
My first major project with Go was BugReplay[1], and I had pretty much the same experience as the author. As someone with a lot of perl and python experience the idea of how restricted the language is stylistically initially seemed like a stumbling block but quickly turned into a huge asset.
Now when I go back to python or perl (or javascript) I'm super conscious of the choices I make regarding type checking and parameter checking.
Only for those that never heard of Mesa/Cedar, Algol-68, CPL, Ada, Modula-2+, Modula-3, Oberon, Oberon-2, Active Oberon, Component Pascal, Oberon-07, C+@, Sing#, System C#, D.