I highly recommend watching Alex Stepanovs A9 lecture series, "Efficient Programming with Components" [0], where he covers the humble min() function, and variants thereof, for at least ~20 hours. During this time he also takes a minor digression in to writing a memory pool for linked-list nodes, while pointing out similarities in the design to a Lisp. It's extremely 'instructive', as he would say, in understanding how he writes C++ code. The sheer amount of code will horrify you, it may even seem unproductive, but I think his objective was really to get everyone thinking about the beauty of the algorithms and the details rather than the objective. His concern for performance, correctness of code, and composition of algorithms is interesting and something I haven't seen presented in real time, in C++, in such a manner before. One example for instance, are occasions where he insists on writing functions backwards, from the return statement up.
If you want a higher level overview on his opinions of C++ and programming etc. The less intense series, "Programming Conversations" [1], is worth a more casual watch.
[0] https://www.youtube.com/playlist?list=PLHxtyCq_WDLXryyw91lah...
[1] https://www.youtube.com/playlist?list=PLHxtyCq_WDLXFAEA-lYoR...
It's also one of the few languages in common use that allows using a wide range of abstraction levels, whatever is desired - I'm not aware of any other language that lets you write inline Asm, procedural, OOP, and functional-style code, all conceivably in the same source file.
Gambit-C.
Also I'd posit that inline ASM is a lot easier to reason about in C++ than it is in Lisp, given to the rigid type structure. You're bound to shoot yourself in the foot in Lisp, even more than in C++.
Perhaps it's just me, but it seems like an awful lot of conceptual baggage to do things that can be expressed with much greater simplicity and without resorting to concepts that need multiple years of expert knowledge of the language to get this "elegance". And i understand the theoretical elegance, it's just that I have to ask myself if this truly makes an actual difference in code style, simplicity, and clarity of language.
Do you have any suggestions on what tools the people doing 'parlor tricks' with C++11 should be using to accomplish them, then? That is, what would you suggest to get to that place without the straightjacket?
Note that at a bare minimum, these supposed tools should give the ability for fine-grained manual resource control, zero-(runtime)-cost abstractions, and performance roughly on-par with C++. As evidence that these hypothetical tools work well for the purpose, we could look for some complex and high-performance software written in them: say, a browser engine, a 3d engine, a kernel, etc., but wait a minute -- these are all things that tend to be written in C++ or plain C.
Instead of glibly dismissing the language that's used to implement, say, every major browser engine, wouldn't it be more productive to ask questions about why people use it? Bonus points if the answer is something more realistic than "They don't know Lisp".
That way, you end up trying to figure out how to make a replacement for it that is an actual replacement -- Rust is a fantastically exciting example of this.
It'll be great when we can all move away from C++, since it's a colossal clusterfuck of counterproductive complexity, but "C++ is a bad language" misses the point in a really uninteresting kind of way.
Duh, Lisp of course. (Or Haskell.)
> Note that at a bare minimum, these supposed tools should give the ability for fine-grained manual resource control
Check. Lisp provides garbage collection, but you don't have to use it. It's perfectly possible to write Lisp programs that do manual memory management. It isn't often done because it's hardly ever a win, but if you really want to you can.
> zero-(runtime)-cost abstractions
a.k.a. macros
> and performance roughly on-par with C++.
The SBCL compiler is pretty good. But one of the reasons that Lisp code is not generally as fast as C/C++ is that Lisp code is safe by default whereas C/C++ code is not. You can make Lisp code unsafe (and hence faster) but you have to work at it, just as you can make C/C++ code safe, but you have to work at it. I submit that in today's world, being safe and a bit slower by default might not be such a bad place to be in the design space.
> these are all things that tend to be written in C++ or plain C.
There is a world of difference between C++ and plain C. C is actually not a bad language if you want to write fast code with relatively little effort and don't care about reliability or security. The value add of C++ over C is far from clear. (I don't know of any OS written in C++. Linus wrote a famous rant about why Linux is written in C and not C++. There are, however, examples of operating systems written in Lisp.)
> wouldn't it be more productive to ask questions about why people use it?
I know why people use it: it's fast, there is a huge installed base, and it's an excellent platform for studly programmers to display their studliness. That doesn't change the fact that C++ has deep design flaws which result in its being incredibly hard to use and extend. And the existence of coders studly enough to be productive in C++ does not change the fact that it imposes an extremely high cognitive load on its users.
Performance? Lisp can give you that, as can OCaml, Haskell, and other better languages. Real time system? There is a mountain of research on real-time garbage collection and on using HLLs for real-time systems. Operating system kernel? OSes were once written in Lisp, and OSes could conceivably be written in other HLLs.
Throw in a requirement to interoperate with a C library and suddenly things get ugly. Yeah, sure, you have an FFI, but debugging across a language barrier is difficult (I have had to do it, it is agony). Suddenly you need to worry about pinning objects so that the garbage collector won't move them while some C library expects them to stay still. In some cases your code basically becomes C but with the syntax of an HLL, and you start to wonder why you did not just write that routine in C to begin with (it would have made your life easier). Performance matters but your compiler needs to set up a trampoline so that your code can provide some kind of callback, and now that is a bottleneck that kills all that other optimization work. Then some joker writes some C++ code, and the rest of your week is spent writing wrapper functions because your FFI cannot deal with the name mangler.
At the end of the day there is no particular technical reason for C or C++ to remain so popular, and a big pile of technical reasons to stay away from such languages. C made a bit of sense in the 1970s when computers were small and the understanding of compilers and programming languages was less well developed. At this point C and C++ are a liability that we are all stuck with. Maybe some day the expense of sticking with C and C++ will outweigh the expense required to switch to better languages, but I am not holding my breath.
Another sign of the lack of coherence of the article is that it displays unoptimized assembly output for the C++ example, then goes on to praise Lisp for being around as good. The optimal assembly is actually two instructions:
0000000000000000 leal 0x1(%rdi), %eax
0000000000000003 ret
Not that it really matters, since it will be inlined into any hot loop in both cases.Personally, if you aren't new to programming per se, I'd go with "C++ Primer" by Lippman/Lajoie/Moo since it smoothly integrates modern C++11 throughout the entire text (instead of sticking it into a separate section, as some of the other books do).
After that, "C++ Concurrency in Action: Practical Multithreading" by Anthony Williams: http://www.manning.com/williams/
...and then the rest of the books from the isocpp list (e.g., Josuttis).
1. Libraries:
The rich ecosystem of available libraries is one of my primary reasons for using C++ for numerics :-)
In fact, it's rich enough that it may be best if you were to specify what kind of number crunching you're interested in -- right now I can only try to give you a very broad/big-picture list of some that I've found useful.
The Standard Library supports (P)RNG with a variety of statistical distributions: http://en.cppreference.com/w/cpp/numeric/random
- Boost.Math Toolkit: http://boost.org/libs/math // and more broadly: http://boost.org/doc/libs/?view=category_Math // and even more broadly ;-): http://www.boost.org/doc/libs/?view=categorized - Eigen: http://eigen.tuxfamily.org/ - GPGPU: http://www.soa-world.de/echelon/2014/04/c-accelerator-librar... - MLPACK: http://mlpack.org/ - NLopt: http://ab-initio.mit.edu/wiki/index.php/NLopt_C-plus-plus_Re... - OpenCV: http://opencv.org/ - Odeint: http://www.odeint.com/ - POCO: http://pocoproject.org/ // note: not numerics, but when you need to exchange data over the net/web, these are pretty good for that :-) - QuantLib: http://quantlib.org/ // note: QuantLib is primarily for quantitative finance, but also has math components: http://quantlib.org/reference/group__math.html - SOCI: http://soci.sourceforge.net/ // note: not numerics, but for when you need database access, it has pretty clean API and is easy to use :-)
2. Talks:
* C9 Going Native: http://channel9.msdn.com/Shows/C9-GoingNative
In particular: + "Bjarne Stroustrup - The Essence of C++: With Examples in C++84, C++98, C++11, and C++14" - http://channel9.msdn.com/Events/GoingNative/2013
+ "Sean Parent - C++ Seasoning" - http://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoni...
* BoostCon / C++Now!: https://github.com/boostcon/
There's _lots_ of interesting talks, so explore yourself :-)
For instance, 2013 Keynote: "Dan Quinlan: C++ Use in High Performance Computing Within DOE: Past and Future" // http://2013.cppnow.org/session/keynote/
// IMHO, it's worth watching these for staying up to date with the broader developments in the field -- e.g., according to the speaker (given who he is I'd assume credibility) most national labs, including Lawrence Livermore National Laboratory in particular, are quite actively adopting C++ (not C) and have been turning away from Fortran for some time now.
HTH! :-)
(To answer your question: linear algebra and optimization. I do a lot of Numpy right now, and I see Eigen in my future...)
While it will take a lot more that just this book to get anywhere I think its a good starting point for anyone with experience with other programming languages who want to see what C++ has to offer.
If we are to talk about types, I'd hope people would look at languages like Haskell or Standard ML—or maybe even ATS, Agda, or Coq—for future direction, not Lisp.
Unlike Lisp, C++ lets one write efficient, generic algorithms that can operate on several types of data. Lisp cannot, and falls back to dynamic type testing, which makes for slower code[1]. Basically your only option in Lisp is to specialize everything manually, or inline everything. Both approaches are extremely poor. As I hinted, Haskell and Standard ML do an even better job than both C++ or Lisp. This is talked about a good bit in this article [2].
(Also, for the record, Lisp has no concept of information hiding, interfaces, or APIs. And no, Lisp's packages are just convenient structures for grouping somehow related symbols together.)
The article talked about declaring function types in Lisp. Many implementations plainly ignore those and they provide no value. It doesn't help that idiomatic Lisp code usually doesn't include such declarations.
Lastly, a lot of the things in this article were SBCL specific, and had little to do with the Lisp language itself.
Like others have said, I don't think any points demonstrate that C++ is converging to Lisp. And if it were, that's probably a bad direction anyway, given the author's initial statements about heading toward an algorithmic language.
[1] No implementation of Lisp has true, flexible compile-time polymorphism or any type-algebraic structure; all inferred types must be concretely realized during the inference.
Also, I'm not a "Haskeller". I do program in Haskell occasionally, though. I'm actually, at this time, a professional Common Lisp programmer.
Dude was talking about Common Lisp which has (IMO) one of the best object-oriented systems in history, from the I-get-so-happy-when-I-can-use-it perspective.
The arguments you make apply equally to Python, btw.
And, for all the smug superiority of the Lisp crowd, the niche that C++ is trying to occupy does seem to be significantly bigger than the Lisp niche...
auto xplusone = [](auto x){ return x + 1; };
While at it, here's how Paul Graham's accumulator generator looks in C++14: auto foo = [](auto n){ return [=](auto i) mutable { return n += i; }; };
This does not affect the point of the article in any major way; just a curiosity.What's interesting from a language perspective is that the C++ folks seem to take the approach of "ugly is better" by essentially not breaking backwards compatibility like Python 3 and Perl 6 did. The "clean break" approach seems to create a new species and hope that the old one goes extinct (didn't happen with Perl, probably won't). But C++ just keeps evolving.
Specialization is when you tell the compiler to use a separate implementation of a template when some or all of the template arguments match something. Template specialization is used in the type traits section of the post.