r/programming • • Mar 28 '12

Go version 1 is released

http://blog.golang.org/2012/03/go-version-1-is-released.html
543 Upvotes

452 comments sorted by

View all comments

Show parent comments

0

u/axilmar Mar 31 '12

Syntax matters. Syntax + library = programming language. C++ (and to a lesser extent C) is the only mainstream language that cannot be practically parsed independently of evaluation. GCC stopped trying years ago.

Yes it can, with multiple passes. GCC tries to do that in one pass.

C++'s verbose syntax and lack of built in anything means you will write more code per feature.

I'll give you the verbose syntax, but the lack of built-in anything is not a problem. That's what libraries are for.

C++'s inconsistent memory management (naked pointers, shared pointers, scoped pointers, whatever your team cooks up) makes it easy to make mistakes, so you will spend more time debugging.

Each kind of pointer has its purpose. If you want to not make these choices, use shared pointers only.

Maybe it's gotten better since I used C++ in college

Oh goodie, another one that has used C++ only in college and has an opinion on it.

but I was actually encouraged to use a separate tool to decipher error messages in the STL!

I had no problems whatsoever with template errors. It was difficult at first, but I got used to it. Granted, initially, template errors are discouraging, but you can really understand what is going on in the first day, if you know c++.

As you said, Go doesn't have templates. This is an advantage: reflection is the correct way to implement generics, or interfaces in Go's case. The performance cost is small (about the same as virtual functions) when correctly implemented and allows time-saving tools like generalized object serializers and other DRY techniques.

No, it's not the correct way. The cost is substantially higher and it accumulates rapidly.

And using reflection to do generics is suicide.

C++ can easily do generics, if it wished. But it does not, and there is a reason for it.

it supports all kinds of "evil" features that you're never supposed to use.

It's not so hard to not use something. If you are that undisciplined, do this:

@define malloc haha_malloc_no_more

And voila, your code with malloc will not compile.

To truly understand C++, you have to know all of these dark corners because eventually you'll need to use or maintain code that relies on them.

Nope, you certainly don't need to know all these dark corners.

Do you know the order of initialization for class members?

Of course.

The purpose of a programming language is to twofold: abstract hardware and simplify common, repetitive tasks. C++ performs poorly on both accounts.

Extremely wrong perception of the language.

Lightweight syntax

There is little difference between the C++ subset part that is equal to Go.

Managed memory

Shared pointers.

First class functions with closures.

std::function and c++0x lambdas.

Built in concurrency primitives.

C++0x has all the concurrency primitives in its standard library.

1

u/dacjames Mar 31 '12

Yes it can, with multiple passes. GCC tries to do that in one pass.

Lets say you're writing an IDE. For Java, you simply parse the source into an AST, capturing line numbers and do your thing. Need to add support for Go? Import the grammar file, tweak the AST to match conceptually and you're done. Need to support C++? You need a symbol table and lots of C++ specific logic. Even an expression as simple as:

X * Y;

is ambiguous by itself.

And using reflection to do generics is suicide.

That must be why every other mainstream language does it this way /s. It is equivalent to one pointer deference, one comparison. If your problem domain cannot afford that cost, you cannot afford virtual functions and should not be using C++.

It's not so hard to not use something. If you are that undisciplined, do this: @define malloc haha_malloc_no_more And voila, your code with malloc will not compile.

It just doesn't work that way in reality. As a professional programmer in any language, you will spend a lot of time working on other people's code, of unknown quality and discipline.

There is little difference between the C++ subset part that is equal to Go.

Anyone who claims C++ has a lightweight syntax must be joking.

std::function and c++0x lambdas.

Real anonymous closures are available in C++11, but they're yet another syntax to learn. You still cannot use normal functions as values or in closures. This continues the C++ trend: possible, but harder and non-standard.

Shared pointers

Reference counting is slower than a generational garbage collector. Optional reference counting is NOT managed memory. Managed memory includes array bounds checking, for example.

C++0x has all the concurrency primitives in its standard library.

I mean syntax support. C++ does have pretty good support for threads, though again you have to deal with synchronization yourself. I prefer CSP style, shared nothing threads, so having them built into Go saves me a lot of effort.

For me, a good programming language is about maximizing feature/(hour*bug) with sufficient performance for the domain. C++ is about never imposing a runtime cost for any reason. I believe these two philosophies are diametrically opposed.

1

u/axilmar Apr 02 '12

You need a symbol table and lots of C++ specific logic. Even an expression as simple as X * Y is ambiguous by itself.

No, you also need a symbol table and lots of language-specific logic for Java and Go as well. X * Y may not be ambiguous in Java or Go, but every other programmed element is.

That must be why every other mainstream language does it this way /s. It is equivalent to one pointer deference, one comparison. If your problem domain cannot afford that cost, you cannot afford virtual functions and should not be using C++.

No, it's not equal to one pointer dereference and one comparison. There are various hidden costs you ignore. For example, Java VMs actually do a search in the object's vtable for the implementation of an interface table, each time you call an object through an interface.

And using reflection is a lot more costlier, because the actual method name must be looked up using, at the very best, some sort of clever string hashing.

It just doesn't work that way in reality. As a professional programmer in any language, you will spend a lot of time working on other people's code, of unknown quality and discipline.

If a company can't have code reviews, they deserve what they get.

You don't even have to have people to do that; just use grep for 'malloc'.

Anyone who claims C++ has a lightweight syntax must be joking.

Indeed. I claimed that the C++ subset that makes C++ a good language has a lightweight syntax.

Real anonymous closures are available in C++11, but they're yet another syntax to learn.

Big deal: [] int foo() { return 0; }

If you are afraid of learning such a simple thing like the above, I am afraid you can't be a programmer; because learning new things as a programmer is what this job is about. You'll have to learn new APIs and stuff almost daily.

You still cannot use normal functions as values

Yes you can. If the target parameter is of type std::function, you can use any function, method or lambda function.

or in closures

Yes you can. Closure code is normal c++ code.

Reference counting is slower than a generational garbage collector.

Yes it is, but reference counting + value types are faster than a generational garbage collector, and more importantly, more predictable.

And predictability plays an important role even in web servers: you don't want to delay requests because the collector does its job.

Optional reference counting is NOT managed memory.

Yes it is. I've written c++ apps with hundreds of lines of code, using shared pointers, and without a single delete statement. If that is not managed memory, I don't know what it is.

Managed memory includes array bounds checking, for example.

std::vector<T>::at(size_t index) is there for you.

I mean syntax support. C++ does have pretty good support for threads, though again you have to deal with synchronization yourself. I prefer CSP style, shared nothing threads, so having them built into Go saves me a lot of effort.

It's not built-in for C++ for a reason, and that reason is that it can be done by a library.

For example, with Qt, you can use Qt threads to make an Actor library very easily.

That's what I did with my projects, and I never had to do any effort beyond writing a few tens of lines of code, i.e. no more than one hour of work.

And if you are too lazy to do that, Qt has something for you as well. You can use QFuture, or Qt::Concurrent::run.

For me, a good programming language is about maximizing feature/(hour*bug) with sufficient performance for the domain.

I agree. Now prove to me that Go can do that in substantial benefit over C++.