Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I was reading the article here: and the part about the "blub paradox" was particularly interesting. As someone who mainly codes in c++ but has exposure to other languages (mostly Haskell) I'm aware of a few useful things in these languages that are hard to replicate in c++. The question is mainly to people who are proficient in both c++ and some other language, is there some powerful language feature or idiom that you make use of in a language that would be hard to conceptualize or implement if you were writing only in c++?

In particular this quote caught my attention:

By induction, the only programmers in a position to see all the differences in power between the various languages are those who understand the most powerful one. (This is probably what Eric Raymond meant about Lisp making you a better programmer.) You can't trust the opinions of the others, because of the Blub paradox: they're satisfied with whatever language they happen to use, because it dictates the way they think about programs.

If it turns out that I am the equivalent of the "Blub" programmer by virtue of using c++ this raises the following question: Are there any useful concepts or techniques that you have encountered in other languages that you would have found difficult to conceptualize had you been writing or "thinking" in c++?

For example the logic programming paradigm seen in languages like Prolog and Mercury can be implemented in c++ using the castor library but ultimately I find that conceptually I am thinking in terms of Prolog code and translating to the c++ equivalent when using this. As a way of broadening my programming knowledge I'm trying to find out if there are other similar examples of useful/powerful idioms that are more efficiently expressed in other languages that I might not be aware of as a c++ developer. Another example that comes to mind is the macro system in lisp, generating the program code from within the program seems to have many benefits for some problems. This seems to be hard to implement and think about from within c++.

This question is not intended to be a "c++ vs lisp" debate or any sort of language-wars type debate. Asking a question like this is the only way I can see possible to find out about things that I don't know I don't know about.

share|improve this question

migrated from May 10 '11 at 5:18

This question came from our site for professional and enthusiast programmers.

See also – quixoto May 10 '11 at 3:52
I agree. So long as this doesn't turn into a C++ vs Lisp debate I think there is something to be learned here. – jeffythedragonslayer May 10 '11 at 4:18
The "blub paradox" is nothing but worthless trolling on Paul Graham's part. It would be easy to make the case that he is a victim of the blub paradox himself: there are things that other languages can do that Lisp can't, but because he uses Lisp he doesn't see the value in them. The problem with this kind of argument is that you can twist it around to turn any disagreement with your position into evidence of your position, and is therefore non-falsifiable. It's equivalent to the question: if a protestation of innocence can be taken as proof of guilt, how is an innocent to defend himself? – Mason Wheeler May 18 at 21:01
@MasonWheeler: there are things that other languages can do that Lisp can't -- Unlikely, since Lisp is Turing-complete. Perhaps you meant to say that there are some things that are not practical to do in Lisp? I could say the same thing about any programming language. – Robert Harvey May 18 at 21:45
@RobertHarvey: "All languages are equally powerful in the sense of being Turing equivalent, but that's not the sense of the word programmers care about. (No one wants to program a Turing machine.) The kind of power programmers care about may not be formally definable, but one way to explain it would be to say that it refers to features you could only get in the less powerful language by writing an interpreter for the more powerful language in it." -- Paul Graham, in a footnote to the trollpost in question. (See what I mean?) – Mason Wheeler May 18 at 22:43

10 Answers 10

Well, since you mentioned Haskell:

  1. Pattern Matching. I find pattern matching to be much easier to read and write. Consider the definition of map and think about how it would be implemented in a language without pattern matching.

    map :: (a -> b) -> [a] -> [b]
    map f [] = []
    map f (x:xs) = f x : map f xs
  2. The type system. It can be a pain sometimes but it is extremely helpful. You have to program with it to really understand it and how many bugs it catches. Also, referential transparency is wonderful. It only becomes apparent after programming in Haskell for a while how many bugs are caused by managing state in an imperative language.

  3. Functional programming in general. Using maps and folds instead of iteration. Recursion. It's about thinking at a higher level.

  4. Lazy evaluation. Again it's about thinking at a higher level and letting the system handle evaluation.

  5. Cabal, packages, and modules. Having Cabal download packages for me is much more convenient than finding source code, writing a makefile, etc. Being able to import only certain names is much better than essentially having all the source files dumped together then compiled.

Edit: formatting

share|improve this answer
A note on pattern matching: I wouldnt say its easier to write in general, but after you read a bit on the expression problem it becomes clear that things like if and switch statements, enums and the observer pattern are all inferior implementations of Algebraic Data Types + Pattern Matching. (And lets not even get started on how Maybe makes null pointer exceptions obsolete) – hugomg May 22 '12 at 19:44
What you say is true, but the expression problem is about limitations of algebraic data types (and about the dual limitations of standard OOP). – Blaisorblade Oct 28 '13 at 0:15
@hugomg Did you mean Visitor pattern instead of Observer? – Sebastian Redl May 18 at 21:18
yes. I always switch those two names :) – hugomg May 19 at 3:06


Try writing it in C++. Not with C++0x.

Too cumbersome? Okay, try it with C++0x.

See if you can beat this 4-line (or 5-line, whatever :P) compile-time version in D:

auto memoize(alias Fn, T...)(T args) {
    auto key = tuple(args);                               //Key is all the args
    static typeof(Fn(args))[typeof(key)] cache;           //Hashtable!
    return key in cache ? cache[key] : (cache[key] = Fn(args));

All you need to do for calling it is something like:

int fib(int n) { return n > 1 ? memoize!(fib)(n - 1) + memoize!(fib)(n - 2) : 1;}

You can also try something similar in Scheme, although it's a bit slower because it happens at run time and because the lookup here is linear instead of hashed (and well, because it's Scheme):

(define (memoize f)
    (let ((table (list)))
        (lambda args
                (or (assoc args table)
                    (let ((entry (cons args (apply f args))))
                        (set! table (cons entry table))
(define (fib n)
        (if (<= n 1)
            (+ (fib (1- n))
                (fib (- n 2)))))))
(set! fib (memoize fib))
share|improve this answer
So you love APL where you can write anything in a single line? Size doesn't matter! – Bo Persson May 10 '11 at 7:13
@Bo: I haven't used APL. I'm not sure what you mean by "size doesn't matter", but is there something wrong with my code that makes you say that? And is there some advantage to how you would do this in a different language (like C++) that I'm not aware of? (I edited the variable names a bit, in case that was what you were referring to.) – Mehrdad May 10 '11 at 7:15
@Mehrdad - My comment is about the most compact program isn't a sign of the best programming language. In that case APL would win hands down, because you do most things with a single char operator. Only problem is that it is unreadable. – Bo Persson May 10 '11 at 7:22
@Bo: Like I said, I wasn't recommending APL; I've never even seen it. Size was one criterion (although a significant one, as can be seen if you try this with C++)... but is there anything wrong with this code? – Mehrdad May 10 '11 at 7:26
@Matt: Your code memoized a function, but this code can memoize any function. These aren't really equivalent at all. If you actually try writing a higher-order function like this in C++0x, it's a lot more tedious than in D (although it's still quite possible... though it's not possible in C++03). – Mehrdad May 10 '11 at 7:35

C++ is a multiparadigm language, which means it tries to support many ways of thinking. Sometimes a C++ feature is more awkward or less fluent than another language's implementation, as is the case with functional programming.

That said, I can't think off the top of my head of a native C++ language feature that does what yield in Python or JavaScript does.

Another example is concurrent programming. C++0x will have a say about it, but the current standard doesn't, and concurrency is a whole new way of thinking.

Also, rapid development -- even shell programming -- is something you'll never learn if you never leave the domain of C++ programming.

share|improve this answer
I can't even begin to think how difficult it would be to create generators in C++ given C++2003. C++2011 would make it easier, but still non-trivial. Working routinely with C++, C# and Python, generators are easily the easily the feature I miss the most in C++ (now that C++2011 has added lambdas). – Nathan Ernst May 10 '11 at 4:12
I know I'll get shot for this, but if I absolutely had to implement generators in C++, I'd have to use ... setjmp and longjmp. I have no idea how much that breaks, but I guess exceptions would be the first to go. Now, if you'll excuse me, I need to go reread Modern C++ Design to get that out of my head. – Mike DeSimone May 10 '11 at 4:29
@Mike DeSimone, can you elaborate (breifly) on how you'd attempt a solution with setjmp and longjmp? – shuttle87 May 10 '11 at 4:47
Coroutines are isomorphic to functors. – GManNickG May 10 '11 at 4:55
@Xeo, @Mike: – Mehrdad May 10 '11 at 6:05

Coroutines are an immensely useful language feature that underpin a lot of the more tangible benefits of other languages over C++. They basically provide extra stacks so functions can be interrupted and continued, providing pipeline-like facilities to the language that easily feed the results of operations through filters to other operations. It's wonderful, and in Ruby I found it very intuitive and elegant. Lazy evaluation ties in to this as well.

Introspection and run-time code compilation/execution/evaluation/whatever are massively powerful features that C++ lacks.

share|improve this answer
Coroutines are available in FreeRTOS (see here)‌​, which is implemented in C. I wonder what it would take to make them work in C++? – Mike DeSimone May 10 '11 at 4:32
Co-routines are a nasty hack to emulate objects in C. In C++, objects are used to bundle code and data. But in C, you can't. So you use the co-routine stack to store the data, and the co-routine function to hold the code. – MSalters May 10 '11 at 8:39
Coroutines in C++: – Ferruccio Jun 2 '11 at 17:48
@Ferruccio: Thanks for the link... there are a few in the Wikipedia article too. @MSalters: what makes you describe co-routines as "a nasty hack"? Seems a very arbitrary perspective to me. Using a stack to store state also done by recursive algorithms - are they hackish too? FWIW, coroutines and OOP came on the scene about the same time (early 1960s)... to say the former's a hack for objects in C seems bizarre... I'd imagine few C programmers back then were interested in emulating objects, >15 years before C++. – Tony Jun 2 '11 at 18:09

Having implemented a computer algebra system in both Lisp and C++, I can tell you that the task was much easier in Lisp, even though I was a complete novice to the language. This simplistic nature of everything being lists simplifies a great many algorithms. Granted, the C++ version was zillions of times faster. Yeah, I could've made the lisp version faster, but the code wouldn't be as lispy. Scripting is another thing that is always going to be easier is lisp, for example. It's all about using the right tool for the job.

share|improve this answer
What was the difference in speed? – quant_dev May 10 '11 at 5:51
@quant_dev: a multiple of a zillion, of course! – Matt Ellen May 10 '11 at 7:28
I never really measured it but I had a feeling the big O's were different. I originally wrote the C++ version in a functional style and it had speed problems also until I taught it to modify the data structures instead of creating new, changed ones. But that also made the code harder to read... – jeffythedragonslayer May 10 '11 at 16:00

I learn't Java, C\C++, Assembly, and Java Script. I use C++ to make a living.

Though, I would have to say I like Assembly programming and C programming more. This is inline mostly with Imperative programming.

I know that programming Paradigms are important to categorize data types, and give higher programming abstracted concepts to allow powerful design patters and formalization of code. Though in a sense, each Paradigms is a collection of pattern's and collections to abstract the underlying hardware layer so you don't need to think about the EAX, or IP internally within the machine.

My only problem with this, is it allow's peoples notion and concepts of how the machine work to be turned into Ideology's and ambiguous assertions of what is going on. This bread's all kinds of wonderful abstractions on top of abstracts to some ideology goal of the programmer.

At the end of the day, its better to have a good clear mindset and boundaries of what the CPU is and how computers work under the hood. All the CPU cares about is executing a series of instructions that move data in and out of memory into a register and performs a instruction. It has no concept of data type, or any higher programming concepts. It only moves data around.

It becomes more complex when you add programming paradigms into the mix because our view of the world are all different.

share|improve this answer

What do we mean when we say that one language is "more powerful" than another? When we say that a language is "expressive?" Or "rich?" I think we mean that a language gains power when its field of view narrows enough to make it easy and natural to describe a problem -- really a state transition, no? -- that lives within that view. Yet that language is considerably less powerful, less expressive, and less useful when our field of view widens.

The more "powerful" and "expressive" the language, the more limited its use. So maybe "powerful" and "expressive" are the wrong words to use for a tool of narrow utility. Maybe "appropriate" or "abstract" are better words for such things.

I started out in programming by writing a whole bunch of low-level stuff: device drivers with their interrupt routines; embedded programs; operating-system code. The code was intimate with the hardware and I wrote it all in assembly language. We wouldn't say that assembler is in the least abstract, yet it was and is the most powerful and expressive language of them all. I can express any problem in assembly language; it's so powerful that I can do anything I please with any machine.

And all of my later understanding of higher-level language owes everything to my experience with assembler. Everything I learned later was easy because, you see, everything -- no matter how abstract -- must in the end accommodate itself to the hardware.

You might want to forget about higher and higher levels of abstraction -- that is, narrower and narrower fields of view. You can always pick that up later. It's a snap to learn, a matter of days. You'd be better off, in my opinion, to learn the language of hardware1, to get as close as you can to the bone.

1 Perhaps not quite germane, but car and cdr take their names from the hardware: the first Lisp ran on a machine that had an actual Decrement Register and an actual Address Register. How 'bout that?

share|improve this answer
You find that choice is a double edge sword. We all seek it, but there is a dark side to it and it makes us unhappy. It's better to have a very defined view of the world and defined boundaries that you can operate in. People are very creative creatures, and can do great things with limited tools. So to sum it up, I'm saying its not the programming language but having talent people who can make any language sing! – Chad May 10 '11 at 8:22
"To suggest is to create; to define is to destroy." Thinking you could make life easier with another language feels good, but once you make the jump, then you have to deal with the new language's warts. – Mike DeSimone May 10 '11 at 10:11
I would say that English is way more powerful and expressive than any programming language, and yet the limits of its usefulness expand every day and its utility is immense. Part of the power and expressiveness comes from being able to communicate at the appropriate level of abstraction and the ability to invent new abstraction levels when nedded. – molbdnilo May 10 '11 at 11:49
@Mike then you have to deal with communicating with the previous language within the new one ;) – Chad May 10 '11 at 16:43

Associative Arrays

A typical way of processing data is:

  • reading the input and construct a hierarchical structure from it,
  • creating indexes for that structure (e.g. different order),
  • creating extracts (filtered parts) of them,
  • finding a value or a group of value (node),
  • re-arrange the structure (delete nodes, add, append, remove sub-elements based on a rule etc.),
  • scan thru the tree and print out or save some parts of them.

The right tool for it is associative array.

  • The best language support for associative arrays I've seen is MUMPS, where associative arrays are: 1. always sorted 2. they can be created on disk (so-called database), with the very same syntax. (Side effect: it's extremly powerful as database, the programmer has access to the native btree. Best NoSQL system ever.)
  • My second prize goes to PHP, I like foreach and easy syntax, like $a[] = x or $a[x][y][z]++.

I don't really like JavaScript's associative array syntax, because I can't create, say a[x][y][z] = 8, first I have to create a[x] and a[x][y].

Okay, in C++ (and in Java) there are nice portfolio of container classes, Map, Multimap, whatsoever, but if I wanna scan through, I have to make an iterator, and when I wanna insert a new deep-level element, I have to create all the upper levels etc. Uncomfortable.

I don't say that there're no usable associative arrays in C++ (and Java), but typeless (or non-strict typed) script languages beats compiled ones, because they're typeless script languages.

Disclaimer: I'm not familiar with C# and other .NET languges, AFAIK they have good associative array handling.

share|improve this answer
Full disclosure: MUMPS is not for everyone. Quote: To give a little more “real world” example of the horror that is MUMPS, start by taking one part International Obfuscated C Code Contest, a dash of Perl, two heaping measures of FORTRAN and SNOBOL, and the independent and uncoordinated contributions of dozens of medical researchers, and there you go. – Mike DeSimone May 10 '11 at 10:17
In Python, you can use either the built-in dict type (e.g. x = {0: 5, 1: "foo", None: 500e3}, note that there is no requirement for keys or values to be the same type). Trying to do something like a[x][y][z] = 8 is hard because the language has to look into the future to see if you're going to set a value or create another level; the expression a[x][y] by itself doesn't tell you. – Mike DeSimone May 10 '11 at 10:23
MUMPS is originally a Basic-like language with associative arrays (may directly stored on the disk!). Later versions contain procedural extensions, which makes it very similar to core PHP. One afraid of Basic and PHP should find Mumps frightening, but others don't. Programmers don't. And remember, it's a very old system, all strange things, like one-letter instructions (altough, you may use full names), L-R evaluation order etc. - as well as non-strange solutions - have only one goal: optimization. – ern0 May 10 '11 at 12:57
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%." -- Donald Knuth. What you describe sounds to me like a legacy language whose emphasis is backward compatibility, and that's okay. Personally, in those applications, I consider maintainability more important than optimization, and a language with non-algebraic expressions and one-letter commands sounds counterproductive. I serve the customer, not the language. – Mike DeSimone May 11 '11 at 1:36
@Mike: very entertaining links you posted, I had a good laugh while reading them. – shuttle87 May 11 '11 at 5:18

A compiled library calling a callback, which is a user defined member function of a user defined class.

This is possible in Objective-C, and it makes user interface programming a breeze. You can tell a button: "Please, call this method for this object when you are pressed", and the button will do so. You are free to use any method name for the callback that you like, it is not frozen in the library code, you have not to inherit from an adapter for it to work, nor does the compiler want to resolve the call at compile time, and, equally important, you can tell two buttons to call two different methods of the same object.

I have not seen a similarly flexible way to define a callback in any other language yet (though I'd be very interested to hear about them!). The closest equivalent in C++ is probably passing a lambda function that performs the required call, which again restricts the library code to be a template.

It is this feature of Objective-C that has taught me to value the ability of a language to pass any type of objects/functions/whatever-important-concept-the-language-contains around freely, along with the power to save them to variables. Any point in a language that defines any type of concept, but does not provide a means to store it (or a reference to it) in all the available kinds of variables, is a significant stumbling block, and likely a source of much ugly, duplicated code. Unfortunately, baroque programming languages tend to exhibit a number of these points:

  • In C++ you cannot write down the type of a VLA, nor store a pointer to it. This effectively prohibits true multidimensional arrays of dynamic size (which are available in C since C99).

  • In C++ you cannot write down the type of a lambda. You can't even typedef it. Thus, there is no way to pass around a lambda, or store a reference to it in an object. Lambda functions can only be passed to templates.

  • In Fortran you cannot write down the type of a namelist. There is simply no means to pass a namelist to any kind of routine. So, if you have a complex algorithm that should be able to handle two different namelists, you are out of luck. You can't just write the algorithm once and pass the relevant namelists to it.

These are just a few examples, but you see the common point: Whenever you see such a restriction for the first time, you usually won't care because it seems such a crazy idea to do the forbidden thing. However, when you do some earnest programming in that language, you eventually come to the point where this precise restriction becomes a real nuisance.

share|improve this answer
I have not seen a similarly flexible way to define a callback in any other language yet (though I'd be very interested to hear about them!) What you just describes sounds exactly like the way event-driven UI code works in Delphi. (And in .NET WinForms, which was heavily influenced by Delphi.) – Mason Wheeler May 18 at 21:10
"In C++ you cannot write down the type of a VLA" [...] -- in C++, C99-style VLAs are unnecessary, because we have std::vector. While it's a little less efficient due to not using stack allocation, it is functionally isomorphic to a VLA, so doesn't really count as a "blub" type issue: C++ programmers can look at how it works and just say, "ah yes, C does that more efficiently than C++". – Jules May 19 at 16:57
"In C++ you cannot write down the type of a lambda. You can't even typedef it. Thus, there is no way to pass around a lambda, or store a reference to it in an object" -- that's what std::function is for. – Jules May 19 at 16:58
"I have not seen a similarly flexible way to define a callback in any other language yet (though I'd be very interested to hear about them!). " -- in Java, you can write object::method and it will be converted into an instance of whatever interface the receiving code expects. C# has delegates. Every object-functional language has this feature because it's basically the point of cross-section of the two paradigms. – Jules May 19 at 17:02
@Jules Your arguments are precisely what the Blub-Paradox is about: As a proficient C++ programmer, you don't see these as limitations. However, they are limitations, and other languages like C99 are more powerful in these specific points. To your last point: There are workarounds possible in many languages, but I don't know one that really allows you to pass the name of any method to some other class and have it call it on some object that you provide as well. – cmaster May 20 at 6:11

This is an old question, but since no one has mentioned it, I'll add list (and now dict) comprehensions. It's easy to write a one-liner in Haskell or Python that solves the Fizz-Buzz problem. Try doing that in C++.

While C++ made massive moves to modernity with C++11, it's a bit of a stretch to call it a "modern" language. C++17 (which hasn't been released yet) is making yet more moves to come up to modern standards, so long as "modern" means "not from the previous millennium".

Even the simplest of comprehensions that one can write in one line in Python (and obeying Guido's 79 character line length limit) become lots and lots of lines of codes when translated to C++, and some of those lines of C++ code are rather convoluted.

share|improve this answer
Note well: Most of my programming is in C++. I do like the language. – David Hammen May 18 at 19:39
I thought the Ranges Proposal was supposed to solve this one? (Not even in C++17 I think) – Martin Ba May 18 at 20:04
"massive moves to modernity": What "modern" features does C++11 provide that were invented in the current millennium? – Giorgio May 19 at 5:54
@MartinBa - My understanding of the "ranges" proposal is that it's a replacement for iterators that are easier to work with and less error prone. I've not seen any suggestions that they'd allow anything as interesting as list comprehensions. – Jules May 19 at 17:12
@Giorgio - what features of any currently popular language were invented in the current millennium? – Jules May 19 at 17:12

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.