Why is the C++ STL so heavily based on templates?
stackoverflow.com
stackoverflow.com
A sample of the interesting sort of algorithm work that you can do when you think this way: http://apfelmus.nfshost.com/articles/monoid-fingertree.html
Edit: See also the Typeclassopedia: http://www.haskell.org/haskellwiki/Typeclassopedia And if you're really interested and want to take it hardcore, Edward Kmett's video on his lens library walks through how you can derive it with this sort of logic: http://youtu.be/cefnmjtAolY?hd=1
I am worried these days that people are avoiding talking about monads not because they are not useful, but because places like HN were saturated with talk about monads a few years back. I remember seeing several blog posts explaining monads as some kind of revelation: like they were overloaded semicolons, or monads were burritos, etc. So let's not try to let the popularity of monads interfere with our respect for their powerful and simple structure.
It's kind of like saying that sets are uninteresting in mathematics because they are too general. The Haskell community still does talk a lot about monads, and they are interesting and useful. Monads are what let us describe things like the difference between IO, ST, and STM. Monads give us generalizations of list comprehensions and give us ways to simulate nondeterministic execution.
In short, monads are still king; but the Haskell community is much more aware of the diversity of useful algebraic structures than it was.
Very worthwhile: http://www.stroustrup.com/dne.html and http://lambda-the-ultimate.org/node/2283
Unfortunately, C++ is a language that fills a niche no-other does - the ability to write genericized systems programming code. For large systems (gcc-sized) it offers a lot of advantages over C (obviously, simplicity is not one of them). I say unfortunately because nobody can argue that C++ is beautiful, but until that niche goes away, C++ will always have a place.
Those of us who like C++ see it as the language it wants to be, not the language that it is dragged in to being by it's C heritage.
> nobody is willing to put in the effort needed to get rid of C
This statement is wrong on multiple levels.
1. People are willing to put in the effort to move beyond C, and it's been happening for four decades. C++, Java, Python, C#, Haskell, Ruby...
2. Getting rid of C for new projects universally is not really desirable. It's still the only thing I would choose for writing the majority of an OS kernel, where dangerous low-level operations are necessary. For the same reason, we will never ditch assembly.
3. Rewriting old C projects in newer languages is often ill-advised. Source code contains the knowledge of those who worked on it, it is used to describe solved problems. Rewriting code means solving those problems over again, relearning the encoded knowledge, and making bugs that were fixed long ago.
If you asked me how my blind date went, and I reply, "She smelled better than the inside of a septic tank," I'm sure you would know what's up.
Wow! How would you propose giving access to low-level operations? Writing in assembly?
> but nobody is willing to put in the effort needed to get rid of C and move the programming world forward.
So, you want me to write DSP code in Python? How is that going to work?
How about making it possible to get low-level pointers and to do low-level operations, but not force programmers to do such things just to do something as simple as concatenate two strings?
"So, you want me to write DSP code in Python? How is that going to work?"
Who said anything about Python? There are a lot of other languages out there. There are Lisp systems that will let you access special CPU opcodes, low-level pointers, memory-mapped I/O, etc. There are hard real-time systems written in Ada.
Even if you could show that C is the absolutely best-performance language for some particular operation, why would you write an entire system in C? If it were me, I would write the one function in C, and then call it via an FFI in a high level language. Why constrain your ability to express your design for the sake of a single function?
Sadly the language didn't gain much traction over the years (for reasons due to library support and lack of environments). With the whole revival of functional (and hybrid) languages, I think that good old structured OOP as Bertrand Meyer envisioned will remain the realm of C++ for performance critical applications and C#, Java (and others) for more entreprisey stuff.
I didn't know about Sather, I'll have a look at it. Thanks for that !
There are now a gazillion programming languages, and new ones popping up every once in a while -- like anal warts.
I'm tired of these fucking evangelists. Seeing these posts on the front page is like getting daily visits from Jahova's Witnesses.
Just use whatever makes you productive and your product do whatever it's supposed to do, and most importantly, shut the fuck up. </rant>
The best we can do is to ignore them altogether. I know it's sometimes hard, but it's definitely more productive that way :)
Almost every truly important software system is either implemented directly in one or both of them, or heavily depends on other software implemented in one or both of them.
In practice, you don't get implementations of languages like Java, Ruby, Python, Perl and Go without C and C++. Even if you're using something like JRuby, you'll still likely end up depending on a JVM written in C and/or C++. And all of this isn't even considering that your software, regardless of the language it's written in, will likely be dealing with an OS written in C and/or C++, and possibly communicating with a database or some other server software written in C and/or C++. These days, C and C++ are nearly inescapable when implementing real-world software.
Unless someone takes the time to free Python from C, by doing something like this:
https://en.wikipedia.org/wiki/PyPy
Really, the reason you see interpreters being written in C/C++ has less to do with any technical quality of C or C++ and more to do with something else you mentioned:
"your software, regardless of the language it's written in, will likely be dealing with an OS written in C and/or C++,"
Bingo. Sometimes software needs to do low-level things, even if the software itself is high-level, and that means the software is probably going to be making system calls. An interpreter for Python is going to have to make some system calls, and it is much easier to do that if the interpreter is written in the same language as the OS's API; most OSes have C APIs, and thus writing a Python interpreter in C makes sense.
"These days, C and C++ are nearly inescapable when implementing real-world software."
I doubt it, considering how much real-world software is being written in Java, C#, Ruby, Javascript, etc. Not all software needs to do things that involve directly deal with the OS. The fact that these systems are often implemented in C does not make C inescapable; it just means that nobody has bothered to free themselves from C yet. There is no technical feature of C that makes it inescapable as a language, it is just what we have to deal with until we put in the effort needed to rid ourselves of it.
And C++ doesn't want anything by itself, as C++ is not a person, but an ugly spec with a bunch of ugly compilers written according to that spec and the funny thing about languages beautiful on the inside, is that such languages will never get rid of their heritage, nor will that heritage become less important.
And IMHO there never was and never will be a mainstream language more ugly than C++, being successful only because people wanted C with extensions and they got it. Sometimes I wish normal people knew what C++ was, because sometimes I have a hard time explaining what absolute ugliness is and the first thing that pops into my head is C++.
I hope he'll update it. The debates over concepts deserve a chapter at least.
There are an awful lot of languages out there; I would be careful with statements like this. I am not sure there is any feature or combination of features in C++ that is not equally good or better in another language.
- support on basically every platforms - ability to write parametrized, typed, compile-time constructs - speed
Speed is overrated for C++. Ada and Lisp can compete with C++ on speed in any task except in cases where there is some special hardware that is giving you a speed boost and which only has tools that support C/C++ (and even then, language support tends to expand over time, so this will only really be a short-term gain). C and C++ actually constrain a programmer's ability to optimize code in some cases; CL-PPCRE, for example, is faster than libpcre because rather than set up a pointer structure and interpret a regular expression, CL-PPCRE creates a compiled, callable function that matches the regex. The lack of support for high-level features winds up hurting C++ in some cases, by forcing programmers to come up with their own way to accomplish the task, which is usually slower than what a mature compiler produces. On the other hand, there are compilers for high level languages that do allow programmers to do low-level optimizations; CMUCL and SBCL, for example, support a form of inline assembly, and have mechanisms that allow programmers to access low-level pointers and other constructs.
So really, what this boils down to is not that C++ is necessarily faster, nor that it's language features are unique, but that it is just a lingua franca of sorts that has some very limited support for some high-level features.
The challenge is to find a better systems programming language. I agree that people have made fast(ih) Lisp compilers, but I don't believe I've heard of large programs that run on any platform being made in them.
My argument is not that C++ is the only language with a macro facility - far from it. However, of the languages which are suitable as systems languages (which means they must be fast), only C++ supports one.
I've heard this argument that high-level stuff allows for more speed, but I've never seen it borne out in practice. (Before my startup, I worked in compilers, so I do have a decent perspective on this - nobody in the programming language community believes Lisp even approaches C++ in terms of speed).
Actually, I lie. Naughty Dog games produced a Lisp compiler for the PS2 (I believe used in Jack and Daxter) that had an amazing reputation for being able use much more of the PS2's power than any other game, as it was able to compile to code that ran on the other vector units and not just the main CPU.
The CL-PPCRE is all well and good, but bear in mind there are other regex libraries that compile to machine code, including YARR which is a JIT. pcre isn't the only option.
That is why the C++ community is today far more interested in generic programming, and why everyone are finally starting to realize that functional programming is quite clever as well. OOP on its own just isn't a pretty sight."
Smalltalk has had anonymous functions in the form of block objects since 1972! And they are so fundamental to the language that all control structures and iteration constructs are implemented using them! Look at the following if/else code in smalltalk:
(...boolean expression...) ifTrue: [...true block...] ifFalse: [...false block...]
That sends an ifTrue:ifFalse: message with two arguments, a true block and a false block (lambdas), and if the receiver, a Boolean expression that should yield either the True or False object, is true, then the first block gets evaluated and the second ignored, and if it's false, than the second is evaluated and the first ignored.
Anonymous functions are a core part of OOP, because OOP is supposed to be a streamlined subset of Lisp, preferably with specialized message-passing syntax. The idea that anonymous functions are some recent, novel addition to OOP, or that functional programming constructs are at odds with "pure" OOP, or that by peppering your C++/Java/C# code with lambdas, your "object-oriented" code has suddenly become multi-paradigm, shows just how distorted an understanding of OOP and functional programming the average programmer, and even language designer, has.
Stroustrup clearly didn't understand OOP or Smalltalk when he bolted classes on to his wretched mess of a language, and that's why C++ looks the way it does, instead of like Objective-C, a language that was a faithful, somewhat successful attempt to add Smalltalk-style OOP to C.
Unlike Java or (I suppose) C#, C++ has been considered multi-paradigm certainly since 1998 with templates and the STL: this is not related to the recent addition of lambdas to the standard. Very little of the popular Boost library can be considered OO, for example, as it generally discourages inheritance hierarchies, as does most modern idiomatic C++.
And all of this is derived from the design choice of making it not-even-compatible with C. To me, that's ideology.
That the compiler doesn't load a bunch of .o files does not mean there's no dependency graph. There is, it's just on header files, which makes things worse. You just moved the "modularity" from the linker/loader stage to the compilation stage. Which is the opposite of modularity. You can't modify a template with LD_PRELOAD. You can't have pluggable templates. If you modify a template, you have to recompile everything that uses it.
The STL never had to be efficient. It just had to be convenient. Anyway, you won't get efficiency from generic code, because real efficiency requires knowing what's the problem you're trying to solve.
I think Go got generics much better. Pass an interface{LessOrEqual} to a Sort and you're golden.
You have to recompile javascript every time you run it, does that mean that that language is incapable of being modular?
I think you are confusing two different types of modules here.
In fact, those parts of STL that can be improved significantly are available from other libraries and are widely used in the industry (like some parts of Boost, some hash tables, etc).
Nowadays C++ is mostly used in environments where efficiency is crucial, and this have been the case for many years already. If you take this away, C++ is wildly inferior to several languages.
C++ in practice has evolved a lot. With modern C++ programming style and techniques, it's actually usable and very practical. If you see code from the 90's though... it's a complete mess. All in all I think it's worth knowing inside out, like C (but they are very different languages and trying to use C++ in a C-ish way will only lead to a 90's style mess).
This I consider one of the main powers of C++ - you can basically choose which level of abstraction do you want; the language will not limit your choices here.
But I agree the learning curve is quite steep, it takes years to really benefit from the language. What I found is a good practice is to define which paradigms/language constructs will be used in a project, and then to stick with those.
The language absolutely limits you in terms of choosing your abstractions. You can only redefine the operators already in the language. Adding a feature like continuations or dependent types would require a rewrite of your compiler. There is no notion of a metaobject protocol. At best, you can get some of the power of these abstractions by using a brittle mess of templates and objects, and you'll be left with code that is almost unreadable as a result.
If you want to see a language that actually allows you to choose any abstraction, even those that were unknown when the language was developed, look at Lisp and its macro system.
It is not like the addition of templates broke C compatibility. This happened long before templates were talked about. Still, C code mostly (Yes, with tricky corners.) compiles with a C++ compiler which is great and is exactly what I would expect from a sub-set of a language. Funnily, first you complain about missing modularity due to headers and then you advocate being compatible with C, whereas exactly that feature is necessary for C compatibility.
As to the efficiency: You can actually know which problem you are trying to solve in generic programming by inspecting the properties of types and optimize according to those properties. See for example the different optimizations in standard libraries when it comes to optimizing copies to memcpy calls when called with appropriate types. There is certainly a lot of generic code that is quite efficient (see std::function which compares to native function calls or hand-written virtual function call operators, very fast vector implementations (llvm, facebook), std::thread). There is, of course, bad generic code as there is bad code in every paradigm.
That's not generics but interfaces. C++ has them too... Kind of, in C++ they are called abstract classes; eventhough you need to inherit them explicitely.
This is why you need to do type assertions when using container/heap, container/list... And this is why math.Min of two integers doesn't work without any extra work. :-)
Go is pretty cool, I like it a lot. But there are fields in which interfaces are way less powerful than generics.
Go allows you to create an interface and then to create implementations of this interface for any type that already exists.
Scala solves this problem by introducing implicit conversions, so it's core design is like C++/Java, but the net effect you get from that is like in golang.
But please, don't call them "go generics", they are called "interfaces". ;-)
Alexander Stepanov who designed STL is very critical of OOP. Stroustrup likes quoting him, mostly to annoy the evangelists.
The C++ "party line" on the Usenet groups back when the OOP craze was at its top and C++ was a hot new upcoming language reflected Stroustrup's view. OOP was a useful technique is certain situations.
This has nothing to do with the "party line" whatever it might be, the C++ is as much "the OOP" as Scheme i.e. you can use its type system to implement some kind of OOP.