Hacker News new | past | comments | ask | show | jobs | submit login
Less is exponentially more (commandcenter.blogspot.com)
235 points by enneff on June 25, 2012 | hide | past | favorite | 122 comments



I think as working programmers, we end up torn between two opposing perspectives with our tools (i.e. programming languages, editors, language features):

On one side, there's the aesthetic of minimalism. Visualize the master Japanese calligrapher seated in an otherwise empty room, table before him. One parchment, one pot of ink, one brush. And he creates the most flawless art one could imagine. Mastery means removing all artifice, leaving only pure creation.

On the other side, take a look at your average real workshop: a mechanic's garage, a woodshop, or an operating theatre. They are filled with tools. Mastery is knowing a hundred different implements, each carefully designed for one or a few uses. Mastery means having tamed a thousand tools and knowing which one is the perfect one to apply to the situation at hand.

Programming languages live on a continuum between these points. Over in Zen land, you've got Scheme and Go, maybe Smalltalk and JavaScript. Over in everything-but-the-kitchen-sink territory, you've got Java, C#, Common Lisp, and C++.

The first image certainly seems cooler: you as code ninja wielding vi and lambdas with deadly precision. It's the aesthetic of the artist and intellectual. The second image is blue collar, the tradesman, the kid who took shop class for four years, the vocational school graduate.

If we accept the second image, that says something deep and maybe unpleasant about how we look at our work. But, honestly, I think the reality is that quality professional work often looks like the second picture. Every time I go to Home Depot and get some random tool that only does one thing (basin wrench, water heater element remover, you name it), it takes a job that would be hours of frustration and turns it into child's play, and the quality of the work is better.

Simplicity is a virtue worth striving for, but I think it's also valid to want tools perfectly suited for certain tasks. The real art is balancing the two.


Your metaphor certainly resonates with me, but there are two mixed concepts here:

1) The 'zen' axis of language syntactic joy.

2) The 'practicality' axis which is a kind of mix of size of the standard library, availability of 3rd party libraries that do Really Cool Useful Stuff and the speed of the resulting binary.

Your toolkit isn't really about the zen axis. It's about the practicality axis, and that's where java with its epic standard library, and c++ with its insanely huge number of 3rd party libraries are the workshop, and go is the empty room with a desk.

I mean, the go standard library is amazing (http://golang.org/pkg/) but its missing some of the features you might want if you're say, trying to build a desktop application on windows...and there just isn't (yet) the 3rd party support for it.

Professional work is, as you say, strongly tied to the practicality axis.

Yet, its worth noting that there are certainly domains that even now go is a better and more practical target for applications than C++ or java, with a comparable runtime speed. Specifically, I'd suggest, cross platform system level tools and web applications.

It doesn't really surprise me that most C++ programmers haven't jumped to go; I'd wager most C++ programmers work on applications that don't cross into these domains.


IMHO, its not fair to compare Go libraries (at this stage) with the more mature implementation of libraries in C++ and Java. That will come with adoption, but even at this early stage, the set of libraries that come with go offer a lot of power.

Agreed Java came out of the gates with a good (??) desktop programming library. Google Go's library on the other hand is very web oriented with the building blocks of http, templating, json all woven in - maybe its a better approach to take, seeing how desktop programming is fast disintegrating into a proprietary, incompatible mess with bottle windows (metro) and apple (ios) locking up their environments.

I agree heartily with the zen metaphor, when programming in Go, I find the language recedes to the background and allows me to focus on the task at hand. That's the hallmark of a great language design.

The very very very fast compilation times (you have to experience this to believe it), helps a lot. Gives it the fast turnaround of a scripting language without any loss of power/ expressiveness.


The point I was making is that right now go has a poorer set of 3rd party libraries than, for example java or c++, and that means that as a practical target it's not as attractive for people writing particular types of software.

It's patently absurd to argue that because go > C++ on the 'Zen' scale, that it's somehow also > C++ on the 'practicality' scale. These two axes are not totally independent (arguably say, the verbosity of java for example, decreases its value on the practicality scale) but they're weakly related.

Having a toolkit like QT makes C++ a vastly superior choice to go for a desktop application, despite the fact that C++ lies somewhere on the dark depths of hell on the 'Zen' scale.

What I was saying, and agreeing with the OP on, is: Pick your tool for your problem.

In some cases, that's Go. In some its C++. In some it might be java; but not having all those tools lying around that people can pickup to use is a major failing for go.

...and sure, that'll change eventually I'm sure; but it's an entirely valid complaint right now


>IMHO, its not fair to compare Go libraries (at this stage) with the more mature implementation of libraries in C++ and Java.

It's not about being 'fair', it's about being practical. If a project has a need for X, a programmer cannot wait until X feature of lib is added to a language to start his work.


> I mean, the go standard library is amazing (http://golang.org/pkg/) but its missing some of the features you might want if you're say, trying to build a desktop application on windows...and there just isn't (yet) the 3rd party support for it.

Actually there are several, here is one:

https://github.com/lxn/walk


Using a hundred different pliars and wrenches doesn't make your car any harder to fix down the road. Using a hundred different types of screw heads does.


I think you make a good point, but I would argue that Go finds that balance. Sure, Go's design is more ideologically motivated than, say, C++, but it is not ideological to a fault. (And I think Rob hints at this in the article.)


I think Go hews to the minimal side, but I agree that it definitely aims to be practical and full-featured. The language itself is small, but not painfully tiny (unlike, say, Scheme), and the standard library is quite nice from what I've seen.


The main difference between your "zen" languages and your "kitchen-sink" languages seems to be whether they've standardized their basic libraries, or whether everybody brings their own. I don't think it's controversial to say that virtually all programmers use libraries (both built-in and third-party).

Javascript and Scheme programmers don't build everything from first principles, and C# and Lisp programmers don't need to study for years more just to figure out which wrench to use. The working-set of programmers in either kind of language is comparable in size and functionality.


If you are willing to accept language as one of the calligrapher's tools I think you will find his workshop to be equally cluttered.


> Simplicity is a virtue worth striving for

I think simplicity is a virtue you should strive for in your designs. How complex, messy, dirty your tools are which you use to create those simple designs doesn't really matter.

In the end you don't see the 2 dozen different kinds of tools a master craftsman used to create the beautiful desk. Nothing dirty and blue collar about that.


Go has some really great features, I've written a few thousand lines in it and enjoyed it, but there are some strange hangups that the go designers have that in the end make me think its going to go nowhere.

1. Rob Pike is immensely proud that the language has no generics, but this means that in the last 2 years, there isnt a proper implementation of a linked list that can hold an arbitrary type, or a min-heap, an ordered map, or a b-tree, or any one of countless data structures that one can take for granted in every other language. And yes, there are implementations that take interfaces, but you have to very odd-looking casts to coerce values in and out of them.

2. Go - or its testing support - doesnt allow a simple assert or EQUALS macro, simply because Rob believes everything should be done with if/then structures. Along with error handling, this makes go tests painful to read.

3. Idiosyncratic handling of pointers and values, leading to confusion everywhere and accidental copies and bugs where people pass by value accidentally because its extremely easy to.

4. Channels aren't really that useful beyond small programs (IMHO, maybe I'm wrong), and by making them synchronous any non-trivial go concurrent program has to reason very carefully to avoid deadlocks.

There are countless similar things. People will put up with these idiosyncracies for a while but move on in the end.


Allow me to respond to your points.

1. Your characterization of Rob's position on generics is not at all accurate. The Go team's view, in a nutshell, is that generics would offer some exciting possibilities for Go (particularly when combined with its concurrency model) but that it is also extremely hard to do generics well. We have put a huge amount of work into defining and refining Go, and we don't want to break it with a bad generics implementation.

There are plenty of "proper implementations" of these collection classes. Your only criticism of them seems to be that they are not type safe. But it is trivial to implement a type safe wrapper around such containers, if you desire it. So the situation is perhaps a little cumbersome, but no worse than C. I don't think this is enough to doom the language.

2. This appears to be a matter of taste. You find Go's tests hard to read. I find them easy to read, as they're not written in some domain-specific testing language. They're just Go code.

If you need asserts in your Go tests, they're trivial to add with an auxiliary package, and thanks to "go get" it is trivial to install and use external packages.

3. I have carefully reviewed the code of hundreds of new Go programmers (I'm a Go readability reviewer at Google and work on the open source project) and I haven't observed the issues you describe here. I sometimes see an initial confusion about addressability, but it is usually just this: http://golang.org/doc/go_faq.html#methods_on_values_or_point...

4. I think you're wrong. Think of any time you've written an event loop or had to rally multiple threads. I'm confident that in most of those cases you could have done it more cleanly with goroutines and channels.

Finally, look at the state of programming today. Most of the languages and libraries that people use are riddled with idiosyncrasies. The Go language and libraries, by contrast, are amazingly regular. This is not just my opinion, but the feedback that I receive consistently from Go programmers around the world.


> So the situation is perhaps a little cumbersome, but no worse than C.

Actually, this is not totally true. C has pre-processor and void * which allows for simple generic data structures with no performance impact. go ties your hands here since you have to use type-assertions which are not free, unlike C casts.

> 4. I think you're wrong. Think of any time you've written an event loop or had to rally multiple threads. I'm confident that in most of those cases you could have done it more cleanly with goroutines and channels.

Goroutines are great, but synchronous channels are not at all easy to use beyond simple producer/consumer models.

I'll also note that for both complaints 1 and 2, you think its trivial for programmers to just do the work, but I though go was all about saving programmer time?


> I'll also note that for both complaints 1 and 2, you think its trivial for programmers to just do the work, but I though go was all about saving programmer time?

Go is "penny foolish and pound wise", to subvert the maxim.

It is indeed trivial for programmers to just do the work, and in return you get an amazingly regular system that saves huge swathes of time grappling with larger issues.

I've noticed this realization occurring to other programmers. It's not at all obvious until you've written a significant amount of Go code.


> The Go team's view, in a nutshell, is that generics would offer some exciting possibilities for Go (particularly when combined with its concurrency model) but that it is also extremely hard to do generics well. We have put a huge amount of work into defining and refining Go, and we don't want to break it with a bad generics implementation.

Wouldn't it have been a good idea to take generics into account from the very start?


This is one of my concerns. Java clearly suffers from having generics bolted on much later and the underlying type system would be different if generics were contemplated from the start. Will Go have similar problems when they eventually add generics?


Actually the Go team has mentioned what happened with Java is a reason why they have not added generics, they have said they wont add them unless they are 100% certain that they are happy with the design and that they will not damage the language.


>There are plenty of "proper implementations" of these collection classes. Your only criticism of them seems to be that they are not type safe. But it is trivial to implement a type safe wrapper around such containers, if you desire it. So the situation is perhaps a little cumbersome, but no worse than C.

"no worse than C" doesn't sound particularly enticing.

>The Go language and libraries, by contrast, are amazingly regular. This is not just my opinion, but the feedback that I receive consistently from Go programmers around the world.

Selection bias?


I tend to agree about the lack of generics - the type of people who design and write standard libraries (e.g. Rob Pike and co.) may find it easy to put these things together, but they aren't representative of the general class of programmers, and there should be easy ways to make typesafe collections available to the average programmer (and making them write the same boilerplate around someone else's empty-interface using code may be mechanical, but it isn't low-effort enough to be "easy"). That said, I generally like the direction Go is taking as a language, and would like to see it succeed.


That.

It's nice for languages to have a "benevolent dictator", but Go insists in a lot of arbitrary but not that good choices like the above.

I would add the bizarro build system (go build et al), that if you want to use you have to follow some rather silly conventions (a little flexibility would go a long way).

The GC also leaves a lot to be desired --they will implement something better eventually, but why wasn't that a top priority in 2012 for a "server systems" language? On 32 bits you are mostly toast with OOM errors, but even on 64 bit the GC is simplistic compared to most modern languages. YouTube, for example, had to jump through several hoops with memory issues to use Go in front of MySQL.

And, while the results are faster than Python/Ruby, they are not that competitive with C/C++ or even Java. The "20% slower than C" claim that you'll read is mostly BS. YMMV.

It doesn't help that if anybody brings up those issues, the general sentiment from the Go community (lists, etc) is also: "you're doing it wrong, reverse course, Go is perfect".

That said, I like Go, if it improves a bit with a 2.0 version, it can go places...


Go language has no syntactic difference between owning and non-owning pointers. Therefore, it is impossible to replace stop-the-world GC with reference counting GC eventually. IMHO that's a flaw in the language design and it's too late to fix it, this train is gone.

Nevertheless, we have other good ideas in programming language design these days. Vala, for example, has robust memory management (so it will have predictable memory use on heavily loaded web or db server), and also "async" methods and "yield" statement (borrowed from Python/C#), which effectively turns a function into a class with locals and instruction pointer converted to fields. That way, function execution can be interrupted and restarted at any moment (e.g. HTTP request handler waiting for database to respond).

Channels, coroutines and cactus stack in Go are great, but there are other worthwhile appoarches to solve C10K problem, and who knowns, maybe yield and async over traditional linear stack is better?


Why would you replace real gc with refcounting?


It would be interesting to know if Rob and company would be using the language if they weren't also the compiler developers.

It's one thing to trust a language with "less" features when you own the compiler and runtime, but another entirely when you do not. Rob and company have the backdoor that any time the compiler is not generating code that is as good as they expect, they can fix it _quickly_! Speaking as a compiler writer myself (albeit a research compiler, Manticore), ownership dramatically changes your attitude towards using a language. Optimization limitations become "small bugs to fix when you run into them" rather than a "reject this tool as unusable" issue.


There's lots of companies using Go for serious work these days. It's not just Google.

Also, Go is an open source project. A company that cared could make their own internal folk and modify it as much as they want.


There seems to be plenty of people that trust Go even if they are not the main compiler and runtime developers, Canonical, Heroku, the BBC, not to mention many startups that have completely bet their business on Go:

http://go-lang.cat-v.org/organizations-using-go


Atlassian is on that list but I know that last year we rewrote our Go code to Python after our main Go developer left.


I've never understood this kind of action. Go is so small you could hold the spec in your hand and it's going to be faster and more efficient than python as well as safer to modify thanks to type safety. If it were haskell, or a similarly difficult language to wrap your head around, I could see wanting to rewrite to something easier to understand. But Go has none of those problems. What could possibly motivate a rewrite?


Hopefully we'd never rewrite Haskell - there's enough people here that know it and Haskell is extremely easy to understand.

The team rewrote from Go to Python for various reasons:

* Tool support (debugging, etc) was supposedly poor

* The standard library wrappers were supposedly buggy

* They had to write a lot of wrappers and libraries themselves

* People on the team were already familiar with Python - after Atlassian's single "Go developer" left, there wasn't much reason to keep it


Not blaming you, since there were people familiar with Python, it's probably good thing to continue using it.

Just thought I'd point out to people that this rewrite was done "last year", which was before Go1 was released march this year. The API was in constant change and it all projects needed constant updating to keep up with weekly releases. (or stick with the r60 with totally different and soon-to-be deprecated API)

API is frozen now and life is good.


> Go is so small you could hold the spec in your hand and it's going to be faster and more efficient than python as well as safer to modify thanks to type safety.

I think it's very naive to think that the value of a language in a corporation is limited to its syntax or compilation speed.


If I had limited my analysis to just those things you would have a point. I didn't though. errnoh provided the justification OP was missing. The pre Go1 api changes where a very fast moving target so reducing that maintenance burden was a valid concern. My response was just consternation at the desire to rewrite something when the language is simultaneously easy to learn, safer to modify, and probably faster and more efficient at the task than the language you rewrote it to.


Not just compilation (which is apple-to-oranges since python is bytecode-compiled and then interpreted/JIT compiled), but also execution speed, which means that you need less hardware to do the same job. That's definitely worth something in some cases.


Certainly. But turn that around --- if all of the major Go developers were at Canonical, even if it were precisely the same language today, would Rob and Google use it?


The Go developers (with, perhaps, the exception of ken - but he's a pretty special guy) have all worked in languages that they didn't design or write the compilers for, so I'm not sure what you're getting at.


Startups have bet their business to any random language, from PHP to Dylan.

It's AFTER the startup phase that you rewrite your messy infrastructure (see Twitter, Facebook, etc), and that's when you need mature and capable tools.


The comment on types reminds me of a very thoughtful comment in _The Structure and Interpretation of Computer Programming_:

"Developing a useful, general framework for expressing the relations among different types of entities (what philosophers call ``ontology'') seems intractably difficult. The main difference between the confusion that existed ten years ago and the confusion that exists now is that now a variety of inadequate ontological theories have been embodied in a plethora of correspondingly inadequate programming languages. For example, much of the complexity of object-oriented programming languages -- and the subtle and confusing differences among contemporary object-oriented languages -- centers on the treatment of generic operations on interrelated types. Our own discussion of computational objects in chapter 3 avoids these issues entirely. Readers familiar with object-oriented programming will notice that we have much to say in chapter 3 about local state, but we do not even mention ``classes'' or ``inheritance.'' In fact, we suspect that these problems cannot be adequately addressed in terms of computer-language design alone, without also drawing on work in knowledge representation and automated reasoning."

The next time your complex type hierarchy starts to fragment, you might want to think about that.


For some reason I find this sentence rather amusing:

"Starting point: C, fix some obvious flaws, remove crud, add a few missing features."

From what I've seen, they've done some good things with this language, and looking backwards from today, it's clear that C is one of its ancestors.

Yet if I was given a blank sheet of paper with the same sentence, I would end up with a completely different language. In other words, this reads to me like shorthand for "Rob, that thing that's in your head, build that" (which is a perfectly legit thing to say -- I've said it myself).

It's like giving a bunch of people the requirement to fix the "obvious flaws" of automobiles, and someone draws a convertible, and someone draws an electric car, and someone draws a motorcycle, and still someone else draws a bus. Looking backward, you can see where it came from, but looking forward, nobody can predict where fixing someone else's obvious flaws might lead.

I kind of want to hold a contest where I take some ordinary thing that everybody uses but nobody loves, and have a bunch of people all design a new one that just fixes the "obvious flaws"!


> Early in the rollout of Go I was told by someone that he could not imagine working in a language without generic types. As I have reported elsewhere, I found that an odd remark.

What I find odd is that he makes this statement, but then doesn't explain which of the following he prefers:

1. Rewriting algorithms again and again for each minor variation of a data type

2. Downcasts everywhere

3. Contorting code to work with the two magic data structures, array and map

Instead he goes on to rant about type hierarchies, which is awfully non-sequitur.


You don't need to pick one of those three. Maps and arrays cover most cases. The rest of the time you can implement capabilities on your types (touched on in the article) and do some type assertions.

The really odd thing about the original statement is that this guy "can't imagine" working without generics. That is a remark that could only be made by someone who is fixated on modeling all problems in terms of type systems.


Not sure what you mean by capabilities, even after looking back at the article. I like how Go's interfaces are sort of like Haskell's typeclasses, and I assume you meant something along those lines, but without parametric polymorphism you're still stuck with one of these three.

I can see myself making that statement, and obviously "can't imagine" is hyperbole, since I've written a lot of C, but I can't imagine taking seriously a new language that doesn't let me reuse data structures. I'm not sure what you mean by fixated on modeling with types.. I don't care about inheritance hierarchies, I just want a priority queue (and a multimap and a graph and a blocking queue oh wait that's yet another built-in special case) that doesn't force me to downcast like in Java 1.4.


It's not an unreasonable way to view the world, though.

"Show me your code and conceal your data structures, and I shall continue to be mystified. Show me your data structures, and I won't usually need your code; it'll be obvious."

-ESR, paraphrasing Fred Brooks


data structure != type


> What it says is that he finds writing containers like lists of ints and maps of strings an unbearable burden. I find that an odd claim. I spend very little of my programming time struggling with those issues, even in languages without generic types.

Rob Pike seems to be doing a kind of programming unlike what most developers do. I fill, empty, filter and analyze values in containers all the time, and I suspect I'm not the only one.

> C++ programmers don't come to Go because they have fought hard to gain exquisite control of their programming domain, and don't want to surrender any of it. To them, software isn't just about getting the job done, it's about doing it a certain way. > The issue, then, is that Go's success would contradict their world view

I'm disappointed that the only justification that he can find to explain why C++ programmers are not embracing Go is "C++ programmers don't get it".


> Rob Pike seems to be doing a kind of programming unlike what most developers do. I fill, empty, filter and analyze values in containers all the time, and I suspect I'm not the only one.

I don't think you are disagreeing, there is a reason Go has built in containers like slices and maps: they are very useful.

Rob said he spends very little time struggling with those issues, it doesn't mean he doesn't work with containers, just that (in Go) it is not a struggle, it is rare for you to have to write your own containers, and when you have to it is not particularly difficult (compared to eg., C).


Here's the video of Rob delivering the talk: https://www.youtube.com/watch?v=JE17r3n1kz4#t=53m5s

IMO it is more compelling when spoken.


The claim that wanting to be able to abstract over types is the same as thinking that programming is about constructing taxonomies is one of the sillier claims I've seen recently.


His claim as I understood it is that the fundamental building blocks should not be types (what something is), but functional capabilities (what something can do). Type abstractions are fundamentally hierarchical (from an abstraction to multiple concrete versions), whereas capabilities are fundamentally about composition (I can do A, B and C).


Type abstractions are fundamentally hierarchical

In C++ or Java they certainly are, but Haskell's type classes, for instance, are much more similar to Go's interfaces.


I don't think anyone is going to say that Haskell's type classes in any way fit the traditional notion of a type. It's more the exception that proves the rule in this case.


I know it's a common saying, but I've never understood how exceptions can prove rules.


It is a very old saying from when "prove" meant what "test" means now. Exception is meant in the sense of exceptional, unusual. "The unusual event tests the heuristic."


It's actually a really simple thing that most people misunderstand (such as the parent). It means that if you only provide an exception, it implies a rule. For example, if you say:

Parking allowed 3pm-5pm

that implies that parking is not allowed at other times.


It's just something stupid that people say when they've been caught over-generalizing.


Pointing out how flexible Haskell's type system is just proves how inflexible type systems generally are. It doesn't really demonstrate that most type systems are useful.


And that's exactly how C++'s template ("generics") mechanism works, which makes Pike's claim seem uninformed.


If that's the case, he's doing it wrong. It's like the pot calling the kettle black.

He essentially argues that types are constraining on other languages based on types, where it is actually in Go that types CONSTRAIN your use of things.

Because obviously different things CAN be held in a container, and a container can hold different things -- but Go doesn't let you do that (except for the officially "blessed" containers).

It is Go that's concerned more about "what something is", in letting you work with it, than, say, Haskell.


Its not just that many programmers want more control. Its also the case that many programmers want more complication. They really prefer the most complicated and difficult way to do things. They don't trust things that are easier or simpler. I think that maybe they believe deep down that ease-of-use versus power is truly a zero-sum game, and you just can't get more of one thing without giving up some of the other. Also, I think that many of them are afraid of losing some of their masculine programmer identity if they adopt an easier way to accomplish things. Also, many of them have invested such an enormous portion of their life and identity to becoming fluent in all of the complications that it is nearly impossible for anything to come around that would make them give up that investment.

But it boils down to the fact that selection of base technologies, like all of the most important human decisions, is generally a NOT rational process, but rather an emotional and subconscious one.

One thing that's interesting to me, and I know this will be hard to buy/comprehend for many Go/C++ programmers, but a similar thing is actually happening with JavaScript versus CoffeeScript.

Its amazing because the languages actually have the same capabilities and the syntactical advantages are so obvious.

Here is an example rationalization against the adoption of CoffeeScript from http://oscargodson.com/posts/why-i-dont-use-coffeescript.htm... :

`` You really need a transpiled language to save you some time from learning the right way to write JavaScript in the first place? Learn JavaScript's pain points and just don't do them.

It's like that C/C++ quote goes:

"In C++ it's harder to shoot yourself in the foot, but when you do, you blow off your whole leg." -- Bjarne Stroustrup. ``


Some people don't trust black boxes because they have been burned too many times in the past. I don't want to make this an age thing, but in my observation the people who are chomping at the bit to jump on the next big thing are generally those who haven't yet really suffered because of someone else's mistake.

Cryptography's got the right attitude. Don't use things that are proven to be broken, but at the same time don't trust anything that hasn't been under the harsh glare of professional scrutiny for a while.


I'm 34. I started teaching myself software development when I was seven. I have done PC assembly, C, C++, OpenGL, Win32, MFC, OCaml, .NET, PHP, Python, Twisted, AS3, JavaScript, WordPress, CoffeeScript and other types of programming. I have suffered because of mistakes in the underlying platform implementation in some cases, but in my experience more often I am suffering because of fundamental design limitations of the platform.

People move on to the next thing because they know it solves fundamental engineering problems built in to the platform they are on that are causing constant problems and they are tired of suffering through that. Such as manual memory management or traditional threading.

For example, back in my C/C++ days, I worked on a number of projects that were threaded and manually memory managed. No matter how genius the team members were we always spent a significant amount of time either guarding against those types of issues or diagnosing them, or working on Make scripts or other build-related distractions.

So that was one reason why I moved to C#/.NET many years ago. The advantage of being able to access source code in open source projects, cost benefit and lack of vendor lock in moved me away from that.

Or for example my main project right now is based on Etherpad which was originally written in Rhino which is a Java-based JavaScript. They saved a lot of lines/characters of code by doing it in JavaScript originally which was good software engineering since less code means fewer defects and JavaScript runs on both the browser and server which is also helpful. However, it was built on Java which has dated overly complicated APIs and Rhino is an inferior JavaScript engine. And we can't get it to stop freezing up/crashing at random times, which according to one of the former Etherpad team members is normal.

So we are following the lead of Etherpad and converting the application to be based on Etherpad Lite which is a running on Node.js which is another next big thing. There are no threads, so I know that can't cause any freezing. The V8 memory management and code generation is state of the art. The system will use an order of magnitude fewer resources than the old one. The asynchronous Node execution model and APIs are obviously superior to Java. At least its obvious to me.


>So we are following the lead of Etherpad and converting the application to be based on Etherpad Lite which is a running on Node.js which is another next big thing. There are no threads, so I know that can't cause any freezing. The V8 memory management and code generation is state of the art. The system will use an order of magnitude fewer resources than the old one. The asynchronous Node execution model and APIs are obviously superior to Java. At least its obvious to me.

All of those assumptions are broken, some more heavily than others...


I imagine using Go to write high-performance code or interact well with system libraries is not easier or simpler than a C++ approach, and certainly having worse results.

Also, the comparison to CS/JS seems unfair as Go is not just a syntax change to C++ and has very different a programming style and design goals.


Maybe it would be better to learn more about Go and rationally evaluate its use in those cases rather than using your imagination.

I'm not sure what you mean by unfair. Its certainly far from an exact analogy but there are interesting similarities.

That is true that Go is not just a syntax change to C++ and that it has a very different programming style. Many of the design goals of Go may be different, but maybe not quite as many as you think. My impression is that a primary design goal for Go is to be a powerful systems programming language allowing high performance processing, especially (but not instead of) via parallelism.


I based my assumption off of a quote I heard that was along the lines of, "It is often better to write in the language of the OS when doing systems programming." My personal experience with FFIs and C bindings was extremely boring and tedious. C and C++ may be worse languages but are the obvious choice when dealing with libraries written in their own language.

> My impression is that a primary design goal for Go is to be a powerful systems programming language allowing high performance processing, especially (but not instead of) via parallelism.

That seems true, although unfortunately the current implementation isn't there yet judging from the Benchmark Game:

http://shootout.alioth.debian.org/u32q/which-programming-lan...

The top implementations for languages like Haskell and CL are both higher level _and_ faster than Go's.

I can't agree more with your quote, "selection of base technologies, [...], is generally a NOT rational process, but rather an emotional and subconscious one." Let's face it, Go is only popular because it's creators are popular. There's nothing really wrong with it, but there's also nothing it truly shines in.


Specifically say you want an application which is both highly concurrent and also binds to some C libraries. How does that actually compare in terms of complexity, ease of adaption for someone with a traditional imperative background, tedium and performance to C/C++ or Haskell/CL?

http://golang.org/doc/articles/c_go_cgo.html

I would also argue that although Haskell and Common Lisp are higher level, they have other issues with complexity, syntax and possibly the actual paradigm, libraries, etc.


>>although unfortunately the current implementation isn't there yet judging from the Benchmark Game<<

The benchmarks game Go programs are notably faster when compiled with 6g for x64 --

http://shootout.alioth.debian.org/u64q/which-programming-lan...


I'm still of the opinion they made a mistake by not having exceptions. When programming in Python exceptions are wonderful because they let me put error handling code in the appropriate place without having to litter all the intermediary code to where errors happen with error flags. (Panic is not the same thing.)

The usual complaint about exceptions is "expense", but the same claims can be made about gc. The Go FAQ is more concerned about people labelling non-exception things as exceptions (so what?) or that try/except/finally is ugly. I agree with the latter, but even worse is littering code with if statements doing the manual equivalent of try/except/finally.


The reason we didn't include exceptions in Go is not because of expense. It's because exceptions thread an invisible second control flow through your programs making them less readable and harder to reason about.

In Go the code does what it says. The error is handled or it is not. You may find Go's error handling verbose, but a lot of programmers find this a great relief.

In short, we didn't include exceptions because we don't need them. Why add all that complexity for such contentious gains?


I'm with the grandparent. Every language that I've used that was created after C has included exceptions, and never once have I missed checking errno.

I can understand why, coming from a C++ context, you'd want to avoid them like the plague, but other languages (Python, Java, Smalltalk, ...) do a good job of making them a first-class citizen in the language, which saves a LOT of boilerplate typing. Seeing call stacks implementing a half-assed exception catching mechanism makes me sad. (Okay, Java only gets half credit here, since its checked exceptions inflict a different kind of boilerplate, but my larger point remains.)

Lack of exceptions is half the reason I'm not interested in writing Go code yet. The other half is that anything that seriously intends to replace C++ does need an escape hatch to allow manual memory management for when the GC's one-size-fits-all approach is simply a poor fit. For a language whose goal was explicitly to replace C++, this is an odd place to be tone deaf. I'm disappointed to see an attitude of "haha stupid C++ programmers don't understand that programmer efficiency is more important than CPU efficiency," instead of realizing that there are valid use cases where you do need to care about this and addressing them.

Which is unfortunate.


Did you miss the part where he says: "We weren't trying to design a better C++, or even a better C. It was to be a better language overall for the kind of software we cared about."


You're missing the forest for the trees. The topic of the article is about how good was motivated by creating a better language for systems software than C++, and hypothesizing why it's nevertheless getting more traction with the scripting crowd than C++ programmers.

"We—Ken, Robert and myself—were C++ programmers when we designed a new language to solve the problems that we thought needed to be solved for the kind of software we wrote. It seems almost paradoxical that other C++ programmers don't seem to care."


> In Go the code does what it says. The error is handled or it is not. You may find Go's error handling verbose, but a lot of programmers find this a great relief.

I'm sorry but you are on the wrong side of history on this question (and I happen to think you're also wrong in your characterization of exceptions).

Forcing callers to deal with error numbers right here right now only gives you the illusion of clarity and robustness but it gives you neither.

Every Go program I read is littered with "err,ok := Foo(); if err {}" every ten lines or so. It's brutally verbose and hides the intent of the code.

And it also forces callers to handle error codes that they might not be able to, while a caller a few stack frames above would do a much better job at it.

We learned all these lessons in the 90's, pity Go chose to ignore them.


I just want to point out that just because go lacks a good way of handling error conditions, doesn't mean exceptions are the best way. Haskell has exceptions, and I wish it didn't. Because it has better options for dealing with error conditions, like Maybe and Either. If you are checking for an error condition every ten lines, those are by far nicer than using exceptions.


> In short, we didn't include exceptions because we don't need them.

I would say that not only I don't need exceptions, I absolutely don't want them.

A really annoying thing about languages with exceptions is how they contaminate code, exceptions are (often hidden and badly documented) part of the interface of libraries and packages which you have to deal with when you least expect it.


> harder to reason about.

I hear this from Rich Hickey about Clojure all the time. I'm certainly not at the brain-power level to fully absorb all the implications of that phrase, but I'm starting to "get it". I think this is probably one of the most compelling things to strive for in a medium that is used to "make stuff", like a programming language.


After using Go for a while (and Python and Java and many other languages with exceptions for years), lack of exceptions is one of my favorite things about Go.

Handling errors is not something magical that you have to worry might happen when and where you least expect it.

Exceptions are specially bad in Python, because often they are not even documented as part of the API, so you are never sure when you call a library what it might or might not throw and when.

And that is without going into how they are abused for convoluted control flow.


I agree that exceptions done badly are poor. That is especially the case with C++ where they were introduced later, and they are one of the things some people omit when picking the subset of C++ they use. I also don't think exceptions should be done without GC. Java's checked exceptions are very annoying.

My experience in Python is the opposite than yours, but then I've only been using it for 12 years :-) Undocumented serious exceptions are no different than Go's panic - they will probably terminate the program. But the usual case is extremely useful and not littering intermediate functions with error handling is wonderful.

And sure they can be abused, but virtually any functionality gives you "power" and that power can be used wrong. That isn't a good reason to take something away from the developers who would use them right.


> Undocumented serious exceptions are no different than Go's panic

They are very different, in Go you only panic() for programmer errors: panic() is never part of any API, when you access any API you never have to worry about whatever it will panic() or not.

Meanwhile in Python any function or method might throw an exception for almost any reason imaginable, but of course most people pretend they don't, because exception handling code would swamp your code.

I have done plenty of Python programming, failure to properly handle exceptions is very common.

> And sure they can be abused, but virtually any functionality gives you "power" and that power can be used wrong.

Exceptions are particularly problematic because they are a hidden part of APIs, and you have to be aware of and deal with this hidden part libraries all the time, not just in code you write.


One school of thoughts is that exception is a non-local goto that might span many levels of calls, and that can be non-trivial to understand. Languages without exception has clear paths of return in a function.


True, but so what. The code I like the best is the code I don't even have to write. Having to write all the intermediary code between where an exception happens and where I'd like to handle it is annoying.

And the "understanding" argument applies to other things, such as using a compiled language instead of assembly or GC instead of manual memory allocation.


That's funny. I don't mind writing code. The code I like the best is the code I don't have to debug.


> I don't mind writing code.

You should mind writing code that the compiler can write for you, which is exactly what you do when you don't have exceptions (you simulate bubbling up the error manually).


>That's funny. I don't mind writing code. The code I like the best is the code I don't have to debug.

The code you don't have to write, you also don't have to debug.

So you SHOULD mind writing code.


The assumption here being that if you do not have exceptions, one must write all the intermediate code. That exceptions are the only way of avoiding this.

While in Go this may be the case, it is not true in general. One could use an error monad to achieve the exact same thing, albeit in a much safer manner.


Sure, and in some next generation language yet to be invented you might not even need the error monad!

But we're talking Go here.


Hm, to summarize what Go does better than C++:

  * Easier to learn
  * Faster to compile
On the other hand, C++ provides

  * Better performance
  * Better abstraction
  * Mature tools
Well, I can understand why C++ programmers do not switch.


Huh, they actually made Go to replace C++. I always figured it had a deliberate intent to be a better C.

I find that being able to define your own numeric types and use them as stack-allocated things that use the standard operations is a pretty big deal in C++. I guess it depends on what you're interested in programming.

Also, having a high enough level that you can actually try writing a general-purpose algorithm library without losing noticeable performance to custom-written versions is something C++ at least tries to make possible. The template system is hairy enough to make it a bit questionable just how well you can pull this off in practice though.

Go doesn't attempt either. The arithmetic is what you get in C, implementor-blessed select types and only regular function syntax for the rest of the stuff. If you want to work with interesting mathematical constructs and write in a system-level language, off to C++ you go. The generic algorithms approach is also pretty much what you get in C with void pointers, with some run-time type information added in. You can get more of both expressivity and efficiency if you write your algorithm to handle a specific type, even when the algorithm doesn't have much that depends on that specific type.

I guess C++ is a different subset of the language for different people. Operating system programming doesn't involve mucking around with tensors or quaternions, and it might also involve more hand-tuned choice structures than an armory of genericizable general-purpose algorithms and data structures. My take on Go was that it's a really nice-feeling higher-level replacement for C, and does most everything except the very nitty-gritty hacky raw-memory juggling better than C, but I run instantly into very obvious stuff I can't do which I'd want to be doing with C++.

One thing I also found very tricky to do neatly in Go was a programming style similar to Unix pipes, where you can deploy single or combined general purpose tools to operate on streams of data. Go does have support for first class functions, which handles the tool bit and can even do the combining part (actual pipe characters would need operator overloading though), but the lack of genericity and a stream idiom kill it. There was the exp/iterable package that provided something like this using goroutines, but that got deprecated as non-idiomatic. I don't know if any replacements have shown up.

I do wonder if I'd like my C++ more if it used the duck typing interface thing from Go though. OO in C++ tends to feel a bit of an awkward fit to me.


Go looks very cool but it solves only a subset of C++ better than C++. For example, I doubt very much Crysis, Battlefield or Modern Warfare could be written in Go on consoles assuming Go even existed on consoles.

Similarly I'm not sure how great it is at client side apps where you need certain code for OSX and different code for Linux and yet different code for Windows. Or how about iOS and Android games, two places that use lots of C++?

So at least for me, while I'd love to get the benefits of what Go is trying to achieve, until it solves the problems I personally need to solve it's unfortunately off my list.

When I am on a project it fits I'm looking forward to checking it out.


Go is certainly not (yet) ready for every task C++ has taken over during the last 25 years.

But I would say that for most tasks, it is more than good enough already.

> Similarly I'm not sure how great it is at client side apps where you need certain code for OSX and different code for Linux and yet different code for Windows.

This is very easy in Go, just name your file foo_windows.go, foo_linux.go, etc. See for example:

https://github.com/howeyc/fsnotify


Define "most". It's not suitable for any app I've written in the last 25 years. But I don't do server work, I do client work. Native apps on Windows, Mac, Linux and consoles.

It might be useful for some command line tools I've written but since nearly every command line tool I've written in the last 25 years has been to make data for my C++ client side apps there's a benefit to being able to share code.

Of course I know that's just one anecdote, mine. If it fits most of your use cases awesome.

For me, one thing that might go a long way to use Go is are cross platform client side libraries like WinForms. Once of the things that makes C# so popular with my crowd is how easy it is to make tools with GUIs. Of course C# also interfaces with native data pretty well. No idea how well Go handles that case


I don't see any reason to prefer Go to the D programming language. D achieves all the major claimed benefits of Go and yet has vastly more abstraction power and better type safety and error handling. The interest in Go is a mystery to me.


Is it really a mystery? It was created by some of the most well known computer scientists of the last several decades and was created by and for systems engineering at Google.


The interest in a language with even more features than C++ is a mystery to me.

If you read the linked article you will realize that the main benefits of Go are precisely from "features" that it omits. D takes almost exactly the opposite approach, and takes C++ and adds even more.


The lack of generic programming in Go is a huge deal. It's vital for modelling complex systems without a mess of runtime checks, and generally leads to clean and reusable designs.

  With D, you can get very close to the generic ideal, "This
  is the last implementation of linear search I'll ever need
  to write." Or binary search. Or stable matching. Or
  Levenshtein distance. I searched around, and it looks
  like D is the only language offering Levenshtein distance
  on UTF strings without copying the input and without
  special-casing per encoding. D just has the abstraction
  power to deal with variable-width entities efficiently
  and within a unified definition (that works with many other
  inputs, such as linked lists of floating point numbers, if
  you want). It's really the last Levenshtein implementation
  I need to write. Now, you may not care about that particular
  algorithm, but there are benefits of that power for many
  structures, algorithms, and design artifacts that might be
  important to you.
http://www.informit.com/articles/article.aspx?p=1621867


>Less can be more. The better you understand, the pithier you can be.

The one real weakness of this idea is communicating with others, if you don't share the same understanding you will lose parts of your audience. This is part of the problem with C++ I have read repeatedly on HN (I don't know C++ myself), that everyone uses a subset of the language, but too many use different subsets.


This is absolutely a problem with C++ and a problem that Go neatly sidesteps via simplicity.

In my career as a C++ programmer (thankfully, I almost never write C++ code anymore), I've met lots of people who used it only as C-with-classes, others who used many more features but avoided templates, others who used templates but only via the STL, others who went whole-hog with template metaprogramming; some who use exceptions for basic flow control, others who avoid that but still use exceptions for exceptional circumstances, some who avoid exceptions altogether, etc.

Having each person use their own subset of the language is fine and dandy if you live in an ivory tower and never need to interface with another developer's code, but of course that is not at all how software development works anymore and eventually you'll be in a situation where you have two chunks of C++ code you need to couple together and they have almost completely alien interfaces to each other (lack of string as a built-in language type also contributes to this greatly, especially since many people avoided the STL for so long).

Go makes a lot of these decisions for you in a way such that doing things in the non-Go way is actively difficult while doing things the Go-way is nearly painless.

If you come into the language wanting to write it like C++ or any other language and you insist that it bend to your will, you probably won't like it. If you come into it with an open mind you start to really appreciate the ways in which it has made decisions for you. Even if you don't agree 100% with the decisions it made, the reasons why those decisions were made can always be reasoned out and the consistency enforced by those decisions is well worth the learning curve it takes to get used to them (IMO).


I was at the GoSF meetup. It was great seeing Rob talk and I think many of you are taking this blog post a bit out of context. The gist of his talk was about the philosophy and history behind creating Go.

For me the talk made me more convinced to switch over to Go. I'm a believer that makings things simple is a lot hard than making things complex and I really appreciate the deliberate approach of the Go team regarding adding features. I really hope they stay true to Rob's philosophy of less is more for years to come.


I'll believe it when I see it - anyone have examples of well-written Go compared side-by-side to well-written C++ to show how it is "more expressive"?

Anyway, the benefit to small languages is that it's much easier to design and reason about a consistent and reusable set of language features. The result is overall a superior design, but worse in programmer productivity. Saying "less is more" is just a Turing tarpit.


> The result is overall a superior design, but worse in programmer productivity.

Go (or its current implementations) might have many deficiencies, but I think almost everyone that has used it for any minimally sized project will agree programming it Go is much more productive than C++.

Some quotes about how productive people are with Go: http://go-lang.cat-v.org/quotes


Less is less, but Less might be a better choice if you're particular problem doesn't merit the additional complexity of More.


If only good programming meant usage of this language over that. Unfortunately language selection has least correlation to program quality. Better practices, frameworks and above all programmer maturity matters. High time programming community thought about creative ways to pass knowledge across. Don't we have enough hammers already?


I'm curious how one can file garbage collection under doing less, especially for a language intended for systems programming.


You might be less curious if you had read and understood the talk. Relevant text:

"That way of thinking just isn't the way Go operates. Zero cost isn't a goal, at least not zero CPU cost. Go's claim is that minimizing programmer effort is a more important consideration."

In a language with closures and Go-style goroutines and channels, the amount of programmer effort required to manage memory would be absolutely immense without a garbage collector.

I believe that "less" as Rob Pike means it doesn't have to do with the complexity of the underlying runtime (though I suspect he'd like that complexity to be as small as possible while getting the job done), but rather the amount of complexity the programmer using the language has to worry about when constructing programs in the language.


"In a language with closures and Go-style goroutines and channels, the amount of programmer effort required to manage memory would be absolutely immense without a garbage collector."

That isn't the whole story though. Microsoft Singularity achieved this with the exchange heap: closures and Go-style goroutines and channels can exist without concurrent GC, or even without GC at all on a per-goroutine basis.


I agree that it's always a target conflict. I'm just not convinced that gc is the way to go in an environment where optimization might become important. GC lets you get a correctly working program easier, but once you are into optimizing runtime performance you quickly loose that advantage, often by simulating memory management with pools. Take a look at the new Obj C with automatic reference counting. It lets you forget about the standard case and only requires you to take action for circular reference by defining them weak - thus it replaces a hard problem to solve with an easy one. For my taste that's the right balance in an environment that is run close to the hardware.


1986 - Brad Cox and Tom Love create Objective-C, announcing "this language has all the memory safety of C combined with all the blazing speed of Smalltalk."

http://james-iry.blogspot.com/2009/05/brief-incomplete-and-m...

Once you're optimizing the runtime performance of Objective-C code, you're suddenly writing in C.

The "close to hardware" thing is an illusion created by the "-C" part.


While that blog post is a fun read, it's a bit of a stretch to quote it in this context don't you think? ;)

"Once you're optimizing the runtime performance of Objective-C code, you're suddenly writing in C."

1) in idiomatic obj c you have already more control over runtime behavior than in managed environments, simply because you don't have to worry about a GC kicking in at a bad time (like "user has touched my interface, expects immediate GUI response").

2) If you do want to dig deeper, yes you go into C programming. However, I don't see what's wrong with that. In a managed environment it's not even possible to do that.

"The "close to hardware" thing is an illusion created by the "-C" part."

It always depends what you mean by "close". In Obj C it's abstracted away but accessible. In a managed language it's hidden by the runtime environment and not accessible anymore. Don't get me wrong, I think that managed languages certainly do have their merrit for many applications. It's just pretty obvious to me that they won't replace languages like C or C++ in the near future. Obj C is something in between - and I like its balance. Obviously it's not well suitable for cross platform development, but that doesn't defy the idea behind it.


I'm not sure what kind of "managed environment" you're talking about, but Go is not one.

1) You're right about GC pauses, but you certainly don't have more control over the memory layout in idiomatic Objective-C than in Go. In ObjC you're mostly dealing with heap-allocated objects (by the way, remember that malloc is not deterministic too), and you don't have control over the objects' memory layout.

In the recent SDK, your typical NSNumber may be a tagged pointer or it may be a pointer to a number on heap -- you don't know, it's an implementation detail.

Hell, you don't even know the big O of NSArray! http://ridiculousfish.com/blog/posts/array.html

Oh, and autoreleasing. Do you know how many objects will be released at the end of your NSAutoreleasePool? Nope -- you don't know how many were allocated by other people's code you called.

2) Again, I don't know what "manage environment" you're arguing against, but from Go you certainly can call C functions. But nobody does this for speed, only for compatibility with existing C libraries, if needed. You're programming in Go, not in two languages.

Go is not a 'managed language', whatever this Microsoft's term means, so I'm not even sure what to answer to your last paragraph.


> In a language with closures and Go-style goroutines and channels...

Is that also filed under doing less? I believe C/C++ programmers aren't flocking to Go because it isn't strictly less. Every language that has tried to replace C/C++ always ends up doing too much. I'd love to see a replacement for C that solves the obvious flaws but doesn't add to much to the basic premise.


We're certainly hoping that Rust is that language.

In particular, we're trying to get the raw no-compromises performance of idiomatic C++ in a practical, memory-safe (and data-race-free) language. That means that our type system is more complex than that of C or Go, but it also lets us squeeze performance out of the machine without sacrificing safety.

We do have an optional per-thread garbage collector (it doesn't stop the world, only the thread), but it's more like shared_ptr than what you'd usually think of as a GC; it's there if you want it on your objects, and you don't have to use it.

(Disclaimer: I work on Rust.)

(Second disclaimer: Go is an awesome language and, as this talk illustrates, we aren't competing with Go; Go and Rust have totally different goals and Rob Pike's languages were quite the influence on Rust.)


There are several of those languages too, but they suffer from the opposite problem: not enough differentiation to overcome the inertia, tool support, and installed base of C.

The most developed attempt that comes to mind is Cyclone http://en.wikipedia.org/wiki/Cyclone_(programming_language).


I agree. In the end, it's not really surprising that C/C++ continue on. Replacements either include too much to be a strict replacement or do too little to warrant the change.


"Is that also filed under doing less?"

Compared to writing concurrent code in C++... yes, absolutely. No question.


Covered by Go FAQ: http://golang.org/doc/go_faq.html#garbage_collection

"Another point is that a large part of the difficulty of concurrent and multi-threaded programming is memory management; as objects get passed among threads it becomes cumbersome to guarantee they become freed safely. Automatic garbage collection makes concurrent code far easier to write. Of course, implementing garbage collection in a concurrent environment is itself a challenge, but meeting it once rather than in every program helps everyone.

Finally, concurrency aside, garbage collection makes interfaces simpler because they don't need to specify how memory is managed across them."


I have a favorable impression of Go after reading this post, however...

The main argument that less is more is essentially the MIT approach of Richard Gabriel's classic Worse is Better concept. It merits mention.


It's not the same argument. Worse is better is about whether it's more important to have a simple implementation (Unix/C/NJ style), or a simple interface (MIT style).

This post is arguing about whether it's important to have a lot of features in a language, or whether fewer features is more powerful.

C++ has a complicated interface and a complicated implementation. So it's neither NJ or MIT style.

My perception is that Go has a simple interface but relatively complicated implementation (relative to C). It's actually closer to MIT style, despite having the Bell Labs/NJ heritage. Examples: garbage collection, segmented stacks, and goroutine scheduling. Not saying that's good or bad, but the "guts" aren't exposed as much as in C. Unix and C let all the implementation details poke out. They have simple implementations but complicated interfaces.

I guess garbage collection should be the canonical example of an MIT style feature. The interface is much simpler, but the implementation is extremely complex. And it does poke through that abstraction boundary and bite you.


> C++ has a complicated interface and a complicated implementation. So it's neither NJ or MIT style.

Yes, in a way C++ is the worst of both worlds.

I'd like to think Go combines from both traditions and comes to a very nice and useful compromise.


The most useful information about Go until now for me:

It was not made to replace C++, rather, it seems that it grew out of frustration of using C++ for some specific project inside of Google. That program needed 45 minutes to compile on a computer cluster!

However, Rob seems to wonder why more C++ users didn't pick up Go, but Python users did. But I believe it's more than obvious: I'm sure that he still can't use Go even as the part of the mentioned 45-minutes-on-cluster compiling C++ project. Go is a system, not something that can be linked to the existing C++ or C or Fortran project. To compare, note that C was made to be able to be linked with Fortran or assembly.

Moreover, I believe that even if he had all the time of the world for rewriting the mentioned 45-minute-on-cluster compiling C++ project in Go, his resulting program would certainly compile faster and most probably "look" nicer on the line lieve but would execute bad enough that nobody would like to switch to his variant, just for the speed and memory usage aspects.

And that's all that it's to be said about Go. Good wishes are one thing, but the execution matters. One the pure performance level, it pays out immensely to replace some project written in Python with Go, on the "what compiler does for you" level too. Python is awfully slow whenever the built-in C code inside of Python and libraries like numpy is not executed, and the errors which you can catch with compiler are much more convenient than the run-time errors. But when replacing C or C++, you simply don't get the execution-level control or memory footprint benefits with Go. "But it's easier to write, especially concurrent programs" argues Rob. Yes, you can read it for every language in existence: for people who are used to the language they talk about, when they write exactly that what they are used to write, it's the easiest language to write in. Erlang people would tell him that Erlang is easiest to write for concurrent programs. It's easy to find the scenario where any language is an optimal one.

But being better or as good as C is not an easy task. The only language which was often quoted to produce even faster code was Fortran. Not that Pascal didn't have the possibility to avoid aliasing problems inherent in C, for the given tasks, numerical computing, Fortran was for enough historical reasons more convenient than Pascal.

"The determined Real Programmer can write Fortran programs in any language." http://www.pbm.com/~lindahl/real.programmers.html For those who don't get it, it's a joke: I quote it in order to finish with: For decades, languages are marketed as the "silver bullets." Go ain't, just like most of them before. I'm old enough to know, some of the most successful aspects of Go: fast compilation, clean declarations and reduced syntax were present in the works of Niklaus Wirth: http://en.wikipedia.org/wiki/Modula-2

Wirth was obviously quite right from the start. And Object Pascal programmers know they had a lot of good sides of Go even twenty years ago. Including not being forced to have constructors.


Now, what would be the ideal language that would be "better than C" in my opinion? Let's call it X. In my opinion, X would be some modification of C with the following properties:

- no headers in C sense -- a limitation that would allow the definitions to be independent of text-based macros.

- the compiling/linking speed of ObjectPascal or Go. That area was the most ignored by "compiler designers" for years, because "hey we're compiler designers" and "linkers are not sexy, compiler are." In reality, the mentioned C++ monster that compiles 45 minutes could be reduced to be compiled to 4 and have all functionality of current C++.

- the full "linkability" to C. If I link a bunch of X files, I can get one OBJ which I can link to the C project. Or I can call from X to C. Both must work. Maybe I would need to link some run-time support additionally, but it must be enough.

- having in compiler "the introspective capabilities" as in D. That is fully ignored by most of compiler writers and I really believe D is on the right track, especially since Andrei Alexandrescu worked for some of such features. If at some point I have some expression and compiler know the type of it, I should be able to query it. If compiler knows the name of something, I should be able to query it and insert the name in my code! If compiler knows some dependency, I should be able to know it in the code, if I need it. Etc.

- built-in ways for decent strings (with counted sizes, not zero terminated), counted arrays, lists etc. I should be able to use them in the declarations/implementations without the overheads of the STL monster that it became. Again I should be able to link the runtime and access elements of these from C too.

So the logic would be: you can shoot yourself in the foot like with C, but you can have a "safer subset" (the compiler should have the switch "compile as unsafe" which would be off, in order to live you the chance to do low level when you must, but to keep most of the code "clean." When most of the "common" arrays, strings, maps, trees are part of the language, in most common cases, the whole programs could be "safe."

Etc. As you see this probably excludes some of cool features of Go like "segmented stack" and concurrency but it can give something much more convenient than C++ and still be as fast and "low-level-to-the-last-byte" usable like C.

I know, it wouldn't appear too creative, it would appear even less "interesting" than Go but I believe it would make a change: the C basis is sound, we still need the language that we know that it cleanly maps to the assembly.

Go is "something above," therefore not so attractive for those that need the "to-the-assembly" level.


It's pretty cool that GO has "regular syntax (don't need a symbol table to parse)." But isn't that most languages don't need the symbol table to parse? Only languages with ambiguous syntax like C++ needs symbol table.


Apparently he wasn't talking about the length of the article.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: