C++, Ruby, CoffeeScript: a visual comparison of language complexity

 

Most people will agree that C++ is a fairly complex language. But just how complex is it? I got curious about quantifying that by comparing the number of concepts a programmer has to understand to learn a programming language in its entirety.

Concepts in my definition include large categories like classes and operators, as well as more fine grained things like if-else statements and while loops. There is a lot of variation in the complexity of different concepts, so their number can only serve as a rough measure of language complexity. Nevertheless, I think it’s interesting.

I chose C++, CoffeeScript and Ruby for my comparison. CoffeeScript and Ruby are dynamically typed so they are significantly different from C++. However, all three are multi-paradigm general purpose languages, supporting (to a reasonable degree at least) object oriented, functional, procedural and generic programming. So this post is about C++ vs. dynamically typed languages.

I think it would also be interesting to make a comparison with other statically typed languages such as F# or Scala but I’m not really familiar with them, so it would be hard for me to do.

CoffeeScript

First up, let’s look at CoffeeScript:

CoffeeScript contains 68 concepts

CoffeeScript contains 68 concepts




It has a total of 68 concepts divided into 8 major groups.

Note that I listed metaprogramming as one concept because it’s largely based on the concept of executable class bodies.

Ruby

Ruby contains 96 concepts

Ruby contains 96 concepts




Ruby is clearly more complicated, with 96 concepts in 11 major groups. It’s got a more sophisticated class model than CoffeeScript, as well as things like constants, blocks and operator overloading.

C++

Finally, here is C++:

C++: 189 concepts, twice more than in Ruby & 3 times more than CoffeeScript

C++: 189 concepts, twice more than in Ruby & 3 times more than CoffeeScript




There are 189 concepts in 18 groups on this diagram, double the number of Ruby concepts and almost 3 times more than in CoffeeScript!

I believe that some of the concepts in C++ (such as name resolution) are also comparatively more complex, with a lot of nuanced rules. The concept of names in C++ is more involved than in the other languages because there are many different categories. In dynamic languages, more or less everything is either a constant or a variable (including class names and function names).

I omitted the concepts of compilation and linking because the other two languages don’t have them.

From the diagram we can see that there are many reasons for the complexity. Part of it is the static type system, another part is templates, yet another part is the name system, as well as the complex class model. The underlying drivers are of course performance and type safety.

What’s not in the diagrams?

I didn’t include a lot of other things that a programmer is required to know in order to use a language in practice:

  • standard libraries
  • language idioms and best practices
  • concurrency concepts
  • design patterns

These things become more prominent when a programmer progresses from learning to mastering a language.

I think that C++ would win the prize for complexity in such a comparison too. For example, there are books like C++ Coding Standards: 101 Rules, Guidelines, and Best Practices (there are in fact 101 rules in there), and Effective C++ containing 55 pieces of advice. These books don’t deal with esoteric situations, they are aimed at normal everyday code. That’s a lot of extra knowledge!

While other languages have their best practices and idioms too, I think their number is quite a lot smaller.

So what’s the point?

My goal isn’t to complain about how huge and incomprehensible C++ is. I believe there is no alternative to C++ for large projects with strict hardware constraints or performance requirements when you take the availability of modern tools, libraries and developers into account.

However, I do think that it’s important to highlight what programming in C++ entails because it has implications for how it’s taught and when it should be chosen for a project.

It isn’t a language that can be picked up quickly. It takes a long time to learn and even longer to master. Because of this, I think there is a lot of value in learning C++ “from the top down”.

With C++11, it has become easier to start with the modern high level subset of C++ (and the standard libraries), and then gradually add on the intricacies and the low level features. In other words, std::shared_ptr comes before raw pointers, lambdas come before functors, and std::array comes before C style arrays.

When choosing C++ for a new project, it’s a good idea to consider the level of experience of the developers or the time available for learning if C++ is new to them.

I think that it’s also good to keep in mind that the complexity of C++ results in a significant disparity in the level of language knowledge between developers, which has to be taken into account in interviews and in providing training. Significant knowledge disparity within a team isn’t pleasant for people on either end of the spectrum.

Finally, here are the diagrams side by side for a quick visual comparison:

 

Keen on mastering C++11/14? I’ve written a book about the C++11/14 features. You can get a VS2013, Clang or a GCC edition.

 

35 Responses to “C++, Ruby, CoffeeScript: a visual comparison of language complexity”

  1. You did not speak the most important language in use today – Visual Basic. It is a much more power soft than other softs you talked of.

     
    • WenFu Zhoudong
    • You’ve got to be kidding.

       
      • Alex Korban
      • Eh, in 2001..

         
        • Tinco
    • Funny, when did Visual Basic became a powerful language?

       
      • Arth
  2. Concepts aren’t in C++11.

     
    • Bob Dole
    • Yep, I know. I was using “concepts” in a traditional non-programming sense.

       
      • Alex Korban
  3. Nice idea!

    Can you please make two other charts: python and C11? So we can also compare ruby python and C11C++11

    Thank you!

     
    • bebna
    • I’m not that familiar with Python but I think it will be quite similar to Ruby. What do you mean by C11? My chart is for C++11 since that’s the current version of the language.

       
      • Alex Korban
      • The C programming language got a year 2011 update just as C++ did. It just wasn’t covered as much in the tech media.

        Wikipedia reference: http://en.wikipedia.org/wiki/C11_(C_standard_revision)
        ISO link: http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=57853

        Personally, I’d like to see these compared to a chart against Scheme. I was probably missing a few things, but my quick mental exercise had 3 groups and only a dozen or so “concepts”.

         
        • seanairt
        • Oh I see. I don’t think a comparison with C would make much sense because it doesn’t allow object oriented or generic programming.

          Scheme would be interesting to see but I wonder if it allows all 4 paradigms (or how well they can be emulated).

           
          • Alex Korban
      • Python is much simpler than Ruby, you should take a look at it.

         
        • fortran
  4. I do not understand why the preprocessor is a C++ concept ? You can use g++ preprocessor for a Ruby file !

     
    • Robert Paulson
    • Umm.. because, like, every C++ program IN THE WORLD uses the preprocessor and every ruby program IN THE WORLD doesn’t. I saw two bears ballroom dancing once, but ballroom dancing is a HUMAN thing. Its not a BEAR thing, you got it? Its not something you’re going to see in a David Attenborough documentary on bear behaviour. No ballroom dancing in nature documentaries. So NOW do you understand why the preprocessor is a C++ concept, even though you CAN use g++ preprocessor for a Ruby file. Holy shit people.

       
      • Dardie
      • Your comment made my day. Thank you.

         
        • Thomaz
      • I enjoyed your explanation, it beat the hell out of car analogies :)

         
        • Alex Korban
  5. I disagree with your last advice about teaching C++, i.e. going from the top down starting with std::vectors and std::arrays and using shared_ptr instead of raw pointers.
    It might be a long hard climbup a tall mountain when you start from the bottom, but the sight is beautiful once you reach the top really.
    A student will miss the feeling of gratitude when he/she does NOT first create his/her own implementation of a (doubly) linked list first and then in a next assignment may use an std::list or std::vector.
    “Raw” pointers are nothing scary when working with a small programming assignment. Sure, there might pop up questions in bigger projects of exactly which class or who should delete that new’d memory, but that’s more of a general design and political question rather than a true programming question.

     
    • rwols
    • rwols, your comment was quite poetic and reflects a common viewpoint, but I guess we’ll just have to agree to disagree.

      Everybody is inevitably heading in one direction though, and that is increasing the level of abstraction. Starting with low level stuff gives people the wrong impression of how C++ should be written, unnecessarily.

       
      • Alex Korban
  6. SFINAE concept is missing in C++.

     
    • Tomáš Siegl
    • Yes, it probably should have been in there.

       
      • Alex Korban
  7. Would someone be able to make a comparison with PHP?

     
    • Brusselsblogger
  8. can i request a comparison for google’s Go Programming Language? so that i can know what to learn, i wanna learn a simple language that can do more, and since i heard that Go programming is an alternative for C++ said by google developers on an interview at channel9

     
    • j0x
  9. From my point of view dynamic casting is also concept. For instance Javascript (CoffeeScript) is very complex in it, e.g. Boolean(expr) is false for all of: undefined, null, false, 0, -0, NaN. And == operator works:
    0 == ‘ \r\n’
    ’0′ == false
    ‘ 0×01′ == true
    ’2′ != true
    ’2′ != false
    ‘true’ != true
    ‘true’ != false
    0 == []
    0 == [0]
    0 != {}
    2 == [2]
    false == []
    true != {}
    false != {}

    This ‘strangeness’ is not unfortunately reflected. It would be nice to extend it.

     
    • Lukas Svoboda
  10. Well… I am interested to see the graph for P” and Brainf**k…

     
    • iveney
  11. Anyone who interested in making similar maps for other languages welcome here https://docs.google.com/folder/d/0ByqCRdN_ceY4dkNMRjNGTjUxUDg/edit

     
  12. Given Rich Hickey’s take on complexity, an analysis of Clojure would be interesting.

     
  13. i think Lua is even more simple than CoffeeScript.

     
    • Alex
  14. Very interesting article! Why not to include containers libraries in the concepts (like standard library or boost)? They are so widely used!

     
    • Thanks Mike. I specifically didn’t include any libraries because I was interested in comparing languages in this instance, and libraries would complicate things.

       
      • Alex Korban
  15. I wanted to learn a new programming language today and I want to thank you-

    I had hear of Coffescript before and was pleasantly surprised to see that it lightweight and only has a few concepts to learn.

    Cool!

     
    • Fred