Your Finances are your own Business Payday loans Another type is online advance
Apr 292009
 

It is a very good idea to learn several programming languages. It makes you a better programmer. But if you want to devote all your energies to becoming a proficient and productive programmer and want to learn one powerful, freely available, high level general-purpose language (not domain specific), what would you choose?

The target audience for this exercise is someone with a couple of years of programming experience.

Here are my criteria for selecting (a non domain specific) language to learn.

1. Programmer productivity: It should provide high level of abstraction so that programmer productivity is high. A fast running application written in C that takes 6 months is — in most cases — not as useful as one that can be completed in 1 month: programmer cost as well as time-to-market considerations.
2. Speed: It should be fast (should approach C in speed). It should preferably have a highly optimized compiler that can generate architecture specific binaries — no JIT can be faster than an optimized binary. Second preference is a compiler that generates byte codes which can be processed by a fast JIT-capable virtual machine. The only virtual machine that fits the bill is JVM.
3. Succinct: The language should not be verbose. This is very important. Brevity is one reason why Python and Ruby are popular.
4. Support for Scripting:You shouldn’t have to learn one language for writing scripts and another for applications. This allows for rapid development in script-mode which can then can be compiled into an application, if required. This along with criteria #1 and #3 implies that you should be able to write a 10 line script that does something meaningful.
5. It should take advantage of multi-core processors without requiring additional effort from the programmer. This is important. Even entry level desktops and laptops have 2 cpu cores in a chip and the number of cores is only going to increase.
6. It should have multi-threading and/or message passing support.
7. It should be a mature and time-tested language with active development, user base and lots of applications.
8. It shouldn’t be difficult to learn for people with couple of years of programming experience. There should be good documentation, books, tutorials, active and helpful community (irc), developer tools and IDE.
9. Platform agnostic: It should not favor or give advantage to one platform. dot net comes to mind as it provides significant advantage to windows platform.
10. Code readability and maintainability: It should be relatively easy for authors and others to maintain existing code.
11. Opensource is a fine model, but if the author doesn’t want to release his/her creation under open-source he/she should be able to do so. After all, bills are not free. This means that reverse-engineering of code shouldn’t be possible. You get this as a by product of #2: it is practically impossible to reverse engineer from a binary; with Virtual machine bytecode, it can be made difficult by obfuscation.
12. Has a test framework that can generate and run tests.
13. Easily call C libraries (Foreign Function interface), for performance and code reuse.

All criteria except #10 are objective and measurable. #10 is to some extent subjective and therefore my bias will be reflected in the choice of language. Some people hate Python as it uses indentation to define code blocks. This makes the code compact but cut and paste of code is error-prone. Others love it. Some don’t like languages like Perl and Ruby where sigils ($,@,@@) are used liberally. People get personal when you belittle or disparage a computer language — and rightly so. If you have invested 10 years in Perl or Lisp, you have a vested interest in defending it and you cannot be objective.

Let’s begin with Common Lisp, Scheme, Fortran, Smalltalk, C, C++, Objective C, Ada, Java, Javascript, C#, D, Prolog, Perl, PHP, Python, Ruby, Groovy, Clojure, Lua, Forth, Factor, Erlang, OCaml, F#, Clean, Haskell, Scala and start the elimination process.

I will eliminate Prolog as it is not a general purpose language.
I will eliminate Lua for the same reason, though it has found a niche in the gaming community.
I will also eliminate Objective-C as it is mainly used in Mac OSX and iphone software. Of late, there has been some resurgence in Objective-C.
Criteria #1 eliminates C and Fortran. You probably already know C anyway.
Criteria #7 eliminates D.

Criteria #2 eliminates Smalltalk. There has been a revival of Smalltalk with Squeak/Gemstone/Seaside. You get very powerful features like continuations that make it easy to write web apps. But speed is a major concern and it also consumes humongous amount of memory. Also, except for GNU-Smalltalk, you have to work within an image and this is highly limiting. Deployment is also an issue as you have to ship the image. #11 is also a concern.

Criteria #10 eliminates Perl. Other reasons are #11, #5, #2. Though Perl is a powerful language, many people consider it to be line noise. Code written in Perl may look alien to the author 1 week after writing it 8-). Perl was the king several years ago when it had no competition; though Ruby and Python were around at that time, they were extremely sluggish when compared to Perl. Perl also has an amazing number of libraries. You can search the online CPAN archive and easily install perl modules or libraries. However, it has a steeper learning curve than other scripting languages. Object oriented functionality was bolted on to Perl in such a klugy and ugly way “bless ($self, $class_name)” that only a mother can love and bless. Perl6 (forever-ware) has been in the making for God knows how many years. But when it arrives, it is supposed to allow the ability to run other dynamic languages also. I think it is DBA (Dead before arrival). Damien Conway (Perl author) says that the reason (more like an excuse) for the delay is that it is an all-volunteer effort. It is likely that the number of volunteers is dwindling as they jump a sinking ship and go to Ruby or Python. Randal Schwartz who makes money off Perl is hedging his bets and touting Smalltalk/Seaside — on a different site from his stonehenge site. There is a huge base of ‘legacy’ Perl software and Perl will be here for years to come.

I will also eliminate PHP. PHP has been mainly used in web apps. Other reasons for removing PHP are the same as Perl: (#10, #11, #2, #5). Note that #10 is a subjective criteria and reflects my bias. Lot of object oriented features have been added in PHP 5. PHP has quietly and without the fanfare attributed to languages such as Python and Ruby, found a niche in web based applications. You are reading this article thanks to a PHP program — WordPress. Whether it is blogging, wiki, cms, forum, picture gallery there are several popular PHP apps to choose from. PHP is not going away any time soon.

I will also eliminate Forth and Factor. Factor has lot of nice features. However, stack based languages have not appealed to the vast majority of programmers. If you enjoyed using RPN Calculators, you will love Factor.

I will also eliminate Ada due to #3, #2, #7 and even #4, #5, #6.

Javascript: I rule out Javascript partly because its initial domain was client side code in browsers (it still is, to a large extent) but mainly for the same reason we don’t program in assembly any more — availability of highly optimizing compilers. In the case of Javascript, the highly optimizing compiler is GWT (Google Web Toolkit) that can generate better code than hand-crafted Javascript. Given that the primary domain of Javascript is client-side code in browsers, that there are several browsers — Firefox, Internet Explorer, Safari, Google Chrome, Opera — each with their own quirks, it is an uphill task to ensure that your Javascript code works on all these browsers. More browsers will be added to the list — for example Android. And Google will keep optimizing its GWT compiler to generate even better Javascript (targeted to each browser), so you don’t need to learn Javascript just to write some JSNI code.

Criteria #1 and #3 rule out a heavyweight — Java.
Criteria #1 says that it should provide a high level of abstraction. One of the must-haves for high level of abstraction is that functions should be first class. That is, functions should enjoy the same privileges as variables: pass functions as parameters to functions, return functions from functions etc. In Java, functions are not first-class citizens.
Java also falls short when it comes to criteria #3 — in the verbosity department, it gives COBOL a run for the money.

I will rule out another heavyweight — C++. The design goal — sound at the time C++ was developed — of being backward compatible with C constrained the language designer. It fails my (only subjective) criteria #10. I would argue that C++ fails criteria #8 as there are so many gotchas. There are many variations of C++. Freeing memory manually is error-prone. It is not for nothing you have books like “Exceptional C++”, “More Exceptional C++”, “More and More Exceptional C++”. Garbage collection techniques have come a long way from the “stop-everything-and-run-gc” days. The slight performance penalty is more than worth paying for in return for not having crashes. In addition, you probably already know C++ and the objective is to learn a new language.

I will rule out C#. C# never really took off and hardly is the Java killer that it was touted to be. C# and F# are both from Microsoft and are programming languages for .NET. Now if a same company produces 2 products named C# and F#, which one will you pick? F#, as it got to be better 8-) Seriously speaking, you can do with F# all that you can do with C# and more. F# (F stands for functional), lets you write both functional and imperative code. It is heavily influenced by the OCaml (Objective Caml) language. F# allows scripting whereas C# doesn’t.

Common Lisp and Scheme excel in many of the criteria but I am eliminating it primarily due to syntax (#10). Though I enjoy writing emacs lisp code and reading (primarily emacs) lisp code, the syntax — code is data, jungle of parenthesis — has not found mainstream acceptance. Reading and understanding code where the powerful macro feature is used liberally — as it would be in advanced apps — would be difficult for many; using macros correctly would also be a challenge. Support for multi-core processors (#5) is lacking (it is quite difficult to do with mutable objects) and native thread support (#6) may not be available in all platforms.

Clojure , from Rich Hickey, is an interesting dynamic language which has lisp syntax but is a functional language that compiles directly to Java VM bytecode. It has built-in support for concurrency, transactions. So, even though it shares the lisp syntax with Common Lisp and Scheme, I am not eliminating it at this point.

We are left with Python,Ruby,Groovy,Clojure,Erlang,OCaml,F#,Clean,Haskell and Scala.

Static Typing for Lazy People: Type inference — One of the biggest advantages touted by people in the dynamic typing camp (Ruby, Python) is that you can be more ‘productive’ as you don’t need to waste time specifying the type. Any debate on static vs dynamic typing will be not unlike that between vi and emacs — religious wars, where you have people on both camps arguing passionately . I can’t think of any advantage of dynamic typing except that it allows the programmer to be lazy and not specify the type. This laziness has a hidden cost in that a lot more time needs to be spent on testing as you have refused the help of the compiler. The productivity gains are more than offset by the additional testing that is required. And if you don’t write good tests you will have problems at run time where there is not much you can do. Why do you want to hobble the compiler and not let it perform better just because you want to avoid specifying the type. Also, I can never understand why you would want to catch a bug at run-time when you can do it at compile time. Here is the kicker: do you want all the benefits of static typing but don’t want to bother entering type? You can have your cake and eat it too. The name for this magic is type inference. To put it simply, you can infer the types from the operations that are performed. Take division operation: a = c/d. We know that you can divide 2 numbers. You cannot divide 2 Strings or 2 enums (unless you have added these definitions). Similarly if you call ‘head xyz’, the head operation applies to a list and therefore xyz must be a list. This is a bit simplistic but you get the idea. This means that the only excuse for not choosing a statically typed language — laziness — doesn’t apply as you can be lazy and still have static types. With static typing a lot of the bugs will be found at compile time. IDEs can take advantage of (specified or inferred) types. Code factoring is lot easier.
So, though Python and Ruby pass criteria #1, they don’t do it by a wide-margin if you include the extra time required for testing. They also pass criteria 3, 4, 7, 8, 9, 10, 13. But they fail my criteria #2, by a wide margin — Ruby and Python are slow. There are some implementations of Python and Ruby on the JVM but they are not ready for prime-time. Ruby and Python are used in a lot in web-frameworks, the most popular being Rails and Django, but they are not known for speed. Native thread support is lacking (#6) and you cannot transparently take advantage of multi-core processors. So I am eliminating Python and Ruby, primarily for #2 and secondarily due to #11, #5, #6 and the possibility of run time errors due to type mismatch. For many use-cases, speed is not a concern and so Python and Ruby are suitable. But if speed is a concern, it doesn’t make sense (in my opinion) to prototype the app first in Python or Ruby and then write parts (or whole) of it in C for speed. If you can prototype in language-x as quickly as you can do it in Python or Ruby but with much better performance, you have best of both worlds.

I will eliminate Groovy. It doesn’t offer much more than Java with a more succinct syntax. You may as well learn Python or Ruby which are also dynamic languages.

I will eliminate F# due to #8 (Platform agnostic). F# runs on the .NET platform. It may run on Mono (.NET on Linux) but may not be as efficient. We need to depend on Microsoft’s roadmap for F#. You can use OCaml as F# is largely derived from it.

That leaves us with Clojure,Erlang,OCaml,Clean,Haskell and Scala.

Message Passing: It is quite difficult to get multi-threaded programs to work correctly. Locking is a nightmare and it is easy to get it wrong, resulting in deadlocks, starvation etc. Conservative use of locking leads to performance issues. Message passing is an effective alternative. It has been used with great success in Erlang.
Ericsson uses Erlang to write massively parallel concurrent programs. Some of these applications have been running non-stop on switches for several years. You can even upgrade a live system (hot swapping). Erlang is easy to learn and fun to use. Processes are very light-weight and you can send messages to processes. Until recently speed (criteria #2) was a concern, but this has changed with the availability of HIPE (High-Performance Erlang Project). String processing in Erlang is quite inefficient as they are stored as a list of (32 bit) integers. While Erlang is quite suitable for certain domains, I wouldn’t call it a general purpose language. It never came out of its niche until recently with the advent of multi-core processors and interest in functional programming. Lack of 3rd party libraries is an issue. So, with regret, I eliminate Erlang.

Haskell and Clean have a lot in common and so I am combining them as Haskell/Clean to get the top 4: Clojure,OCaml,Haskell/Clean and Scala. At this point, I have to eliminate Clojure. Though it has a lot going for it, the Lisp syntax will still be an issue for most people (#8, #10).

Now we are left with 3: OCaml, Haskell/Clean and Scala. These 3 languages have several things in common.

  • All use static types
  • All use type inference, so that you get the benefit of static typing without having to specify types. Scala’s type-inference is not as complete as Haskell — types for function arguments need to specified.
  • Provide high-level of abstraction (for e.g higher order functions) (Criteria #1)
  • Fast: OCaml approaches C in speed, Haskell/Clean are not far behind. These can be compiled to architecture specific binaries. Haskell frequently wins the Great Computer Language Shootout. Scala compiles to Java byte code and thus takes advantage of the fast JIT compiler. (Criteria #2)
  • Succinct (Criteria #3)
  • Scripting Support (Criteria #4)
  • They are functional languages. Haskell and Clean are pure functional languages. Rich Hickey who designed Clojure says — and I agree — that “Mutable objects are the new spaghetti code”.
  • Because they are functional languages, it is much easier to take advantage of multiple-cores. Multi-Core processors are here to stay and I can say that sooner or later you will be programming in a language that provides support for functional programming.
  • They also satisfy criteria #9, #11,#12. Regarding #12, Haskell has something called QuickCheck. Scala has ScalaCheck which started out as a port of QuickCheck. They automate unit testing and test case generation.

My favorite is Haskell as its syntax is absolutely beautiful (personal opinion) — No unnecessary symbols, punctuation or words. It comes close to writing math that can be compiled into an efficient binary.

Regarding OCaml, while it has a rare combination of providing a very high-level of abstraction and at the same time almost matching C++ in speed, I find its syntax ugly — this is personal opinion. We are all used to + as a symbol for adding, – for subtraction etc; and it is natural to write 5+10 or 5.5+12.5. However, it doesn’t work like that in OCaml. This was a deal-breaker for me and I couldn’t go past that and learn about what the language had to offer. To find the average of 2 numbers you have to write “(a +. b) /. 2.0;;”. To add integers you need to use ‘+’, to add floats you need to use ‘+.’. Similarly for the other operators.

Scala:The language is the brainchild of Martin Odersky, ACM Fellow. He co-designed Java Generics. He implemented Java Generics. His Java+Generics compiler was adopted by Sun as the official Java compiler more than 10 years ago — with the generics switched off, until they became part of the language in Java 5. If you have been programming in Java, you have been using Martin’s Java compiler. It is one of the few languages that supports both threads and message based concurrency. Message based concurrency is based on the Actors model (like Erlang) and it is a Scala library and not part of the core language. It supports both object-oriented programming and functional programming and attempts to unify them.
Functions are values and values are objects. Therefore functions are objects. Unlike Java which has primitive types int, float etc, Scala is completely object oriented. Numbers, characters, booleans, functions are just objects
A big deal is made of duck typing in languages such as Python and Ruby. In Scala you have “Structural typing” which is Duck Typing done right. While not as powerful, you get compile time checking and no run time overhead.

Scala is a huge language with lots of features: traits, abstract types, higher order functions, closures, native threads, concurrency (Actors), xml processing, implicits, pattern matching, partial functions, monads. You can start using it right away and slowly learn about the more powerful constructs. You can easily write a DSL (Domain Specific Language) using scala. There is however a drawback of a functional language like Scala (or Clojure) that runs on top of Java Virtual Machine: it is that recursion is a common paradigm in these languages but the JVM doesn’t allow optimization of tail calls.

Scala, unlike OCaml and Haskell/Clean satisfies criteria #7 and #8. The extensive set of Java libraries can be put to use.

Scala, unlike OCaml and Haskell/Clean satisfies criteria #8. OCaml and Haskell/Clean have a much higher learning curve than Scala. Haskell is a pure functional language and you have to use something called Monads for side-effects. Scala is much easier to learn for the majority of programmers who have been programming in the imperative style.
With Scala, you can start with imperative or object-oriented style of programming (think of it Java without the verbosity) and migrate slowly to the functional features. Even if Martin Odersky’s attempt (experiment as he puts it) to unify functional and object-oriented style of programming doesn’t pan out, Scala can still be a successful language.

Lift is a web framework written in Scala. You can create web apps as easily as you can do with Rails and Django but it will typically run 4 to 6 times faster, use less CPU and it will be lot more scalable.

So, for the reasons mentioned above, I will remove OCaml, Haskell and Clean from the list and declare Scala the winner.

To give a flavor of a Scala program written in imperative style, here is a script I wrote to answer a question posed by Cedric Otaku in his blog. You don’t need to write a program to answer his question but you can verify it using a simulation. Otaku wrote it in Ruby; my Scala version is equally concise.

Here is a sample program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
 * Question: Do you want to play this game?
 * You put down some money and roll a die between 1 and 100
 * Depending on your roll:
 *    1-50: I keep your money.
 *   51-65: You get your money back.
 *   66-75: You get 1.5 times your money
 *   76-99: You get 2 times your money
 *     100: You get 3 times your money
 * Do you want to play?
*/
 
object game { // object is used to define a singleton class
 
  // alas, type inference doesn't work for function args.
  def play(bet: Double, numPlays: Int)  = {
    // parameter values can't be changed
    import java.util.Random // imports can be inside function
 
    // val is like final in java or const in C
    val r = new Random()
    var moneyStart, money = numPlays * bet
    // type of moneyStart and money need not be specified.
    // However, unlike python or ruby, they are inferred as
    //  Double at compile time. Similarly for r and dice.
 
    for (i <- 1 to numPlays) {
      var dice = r.nextInt(100) + 1  // roll the dice
      if (dice <= 50)
        money -= bet
      else if ( (dice >= 66) && (dice <= 75) )
        money += 0.5 * bet
      else if ( (dice >= 76) && (dice <= 99) )
        money += bet
      else if (dice == 100)
        money += 2 * bet
    }
    printf("%6.0f$ became %6.0f$ after %6d plays: " +
           "You get %.2f for a dollar\n", moneyStart,
           money, numPlays, (money / moneyStart))
  }
}
 
game.play(1.0, 100000) // Each bet is $1, play 100000 times
game.play(1.5, 5000)
game.play(4.0, 10000)

Run the script:
scala game.scala
100000$ became 80426$ after 100000 plays: You get 0.80 for a dollar
7500$ became 6134$ after 5000 plays: You get 0.82 for a dollar
40000$ became 31922$ after 10000 plays: You get 0.80 for a dollar

  44 Responses to “If you have to learn just one programming language”

  1. wonderful analysis. It would have been more comprehensive had you considered things like example code, language history/legacy, how good the standard library is etc. Ultimately, language is for people to use. If a language got a great user base, it will be a popular even if its actually lousy. This effect actually snowballs. Lousy languages become more popular because its already got a good crowd. I loved the article though.

  2. you should take a look at Fan

  3. I should have included Fan in my list of languages. A while back I briefly looked at Fan. Fan has many interesting features. I will compare Fan against my 13 criteria and post a reply soon. However, the primary reason for the creation of Fan — portability between .NET and Java — may have performance implications. The Fan website says “The primary reason we created Fan is to write software that can seamlessly run on both the Java VM and the .NET CLR. We built Fan from the ground up to tackle portability between these VMs. Fan’s source language compiles into fcode – a bytecode representation that can be translated into both Java bytecode and IL easily. This translation is typically done at runtime, which enables you to deploy Fan modules as a single file and have them run on either VM.” A bytecode that is converted to another bytecode at runtime is bound to have performance implications. However, I need to research this a bit more.

  4. A bytecode that is converted to another bytecode at runtime is bound to have performance implications. However, I need to research this a bit more.

    Fan pays the same JVM startup penalty as Java and Scala. The translation from fcode to bytecode tends to be a very small percentage of the total startup time (and can be pre-compiled to bytecode if you want to avoid it all together).

    But once running, Fan will generally perform as well as Java or Scala.

  5. “C# never really took off”

    Are you out of your gourd? Those are some of the most prolific job opportunities available.

    1. Strong demand for the language. Let’s be pragmatic. This is the most important criteria.

    Criteria #14 effectively rules out Clojure, Erlang, OCaml, Clean, Haskell and Scala. =)

  6. I do like Scala but I chose Erlang. Erlang does have a good number of frameworks available. The best one being Erlang-web. The one weakness that Erlang has against Scala is documentation. The Erlang docs are written for longtime CS students and programmers not web developers. But it will get better.

    That being said I am glad that Erlang made it so far down on your list. Maybe it will be the top candidate in few more months.

    Get started with Erlang for the web in 5 minutes

  7. pb, Can you back up your statement with facts? If “C# has some of the most prolific job opportunities available” then it won’t have a 4% share in TIOBE index, which is “based on the number of skilled engineers world-wide, courses and third party vendors”. More programmers would have jumped on the C# bandwagon to take advantage of the prolific job opportunities. Even Visual Basic has double the share. Java’s share is coming down but it is still over 19%. So, in that context I meant “C# never really took off”. C# was designed by the one of the biggest companies in the world to be a “Java-killer” and that didn’t happen — and this despite that fact that windows is by far the most dominant platform and C# was designed to take advantage of it via .NET.

  8. So much theoretical mumbo-jumbo. Your criteria are flawed and the post is pointless.

    1. If you want to use one, and only one general purpose language then it has to be ubiquitous. By definition, it can only be JavaScript because it runs on the server side, runs in all major browsers on all platforms, not hard to learn, etc. etc…

    2. There is good reason why “de-normalized” actually works rather than the idealistic “normalized”. Come to think about it. World as it is, is made of different kinds of niches and different languages serve different niches. (Hint: Niches also include human elements.)

    3. Try running this code snippet in Scala (which explains why Functional programming implementations suck on the JVM, thanks to the lack of TCO):

    def odd1(n: Int): Boolean = { if (n == 0) false else even1(n – 1) } def even1(n: Int): Boolean = { if (n == 0) true else odd1(n – 1) } even1(9999)

  9. Jason, If “Strong demand for the language” was one my criteria and the most important one, my post would have been a very short one — and I wanted to write a long article 8-). The language that by far has the most demand continues to be Java.

    The article is for some one with a couple of years of programming experience. Java is taught in most colleges as a way of introducing programming concepts. When you take a up a job, depending on the company you join, you will be most likely be working predominantly in one of the following languages — Java, C, C++, PHP, Python, C#, Perl, Ruby, or Visual Basic. Unless you join one of the hottest companies — Twitter — where you may be programming in Scala.

    In the TIOBE index, next to Java (19%) is C (16%) and C++(11%). You may already know C or C++, and I wanted to provide some guidance on picking a new language to learn. For most domains, C and C++ are way past their prime. How many more times do you need to patch your machine to fix buffer overflow attacks?

    No matter what language you program in now, unless you are retiring soon, there is a functional language in your future. Multi-core processors are here to stay and you cannot easily take advantage of them when you have mutable state.

    If there are a million people who know how to program in Java, adding yourself to that list hardly differentiates you.

  10. “no JIT can be faster than an optimized binary”

    It might seem counter-intuitive, but this is not true at all, quite the opposite is the case (theoretically at least, and increasingly becoming so in practice).

    JIT can perform many optimizations that static compilers can’t. For example, branch prediction can become more accurate based on runtime information (which might be different on each run of the application). Methods can be de-virtualized and inlined, and even virtualized again if an overridden method is loaded post-JIT. Garbage collection is getting better and better and can provide huge benefits, eg due to memory locality improving cache hit rates. The JIT can take advantages of specifics of the hardware it is currently running on (cache sizes, CPU cores, register counts, …) whereas static compilation often forces lowest-common-denominator decisions to be made. Other techniques like escape analysis and compressed OOPS again give the edge to JIT compilers.

    Of course there’s some overhead in JIT, but it’s not as bad as you might think and the benefits from the above examples can significantly outweigh the costs.

    I can think of plenty of other cases where JIT can win out over static compilation (and there is a lot of VERY promising research continuing in this area) but hopefully the above is enough to give you a bit of an insight into why, counter-intuitively, JIT will likely win out over static compilation in the not-too-distant future.

  11. Chris,

    You make some very good points. I stand corrected. Thanks for taking the time to write a detailed comment. This favors all JVM based languages such as Java, Scala, Clojure, JRuby etc.

  12. Shantanu,

    I welcome criticism as long as they are backed up with reasons. However, by declaring my post pointless and my criteria flawed, you have lost all credibility.

    If you want mumbo-jumbo, it will be your comment — “de-normalized” actually works rather than the idealistic “normalized” — whatever that means.

    Ubiquity is not one of my criteria. Saying Javascript is ubiquitous because it also runs on the server is silly. It hardly has any meaningful presence on the server side. Javascript is certainly ubiquitous in the client side: my point is that just because Intel machine code is ubiquitous in computing doesn’t mean that we need to program in Intel assembly. Google has effectively made Javascript into a derived language.

    Here’s the proof: Please take a look at a simple javascript+html application I wrote: http://mortgage-calc.appspot.com There is no server side component here — once the Javascript is loaded into your browser, you can use the app offline. You can run this app on Windows, Mac or Linux; on Firefox, Safari, Chrome, IE or Opera. To handle browser quirks, my Javascript code is individually tailored for each browser — you won’t see code like “if browser is IE then do x else if browser is Firefox do y”, as that increases code size (download time) and affects performance. So, what is the big deal? It is that I don’t know Javascript. I used Google’s GWT. You won’t be able to make sense of the Javascript code delivered to your browser as GWT obfuscates it, giving the additional advantage of reduced code size which translates to faster downloads. Another application I wrote with GWT is a Math Quiz program. To see more impressive examples, checkout the GWT website. It is not for nothing that Google declares “Faster AJAX than you’d write by hand”.

    I had mentioned in my post that one of the disadvantages of a functional language that runs on top of JVM is that recursion is a common idiom and the JVM doesn’t optimize tail calls. You are saying the same thing and I have to agree. Clojure works around this and provides a special operator called recur. Good programmers understand the strengths and limitations of the language they use. No language is perfect. If this is a deal-breaker for you then OCaml, Haskell, Clean, Erlang or F# should suit you just fine.

  13. Prolog IS a general purpose programming language, as general as the languages which made your short list.

  14. I should have written more about Prolog, Lua and a few other languages but in the interest of brevity, I didn’t. Any Turing-complete language is by definition a general purpose language. You can write any program in Prolog that you can write in the other languages mentioned — and in some cases more elegantly. But its intended and actual domain of use is logic programming with Horn clauses. It is a declarative programming language that is suited fine for theorem proving, expert systems, dynamic programming, planning, AI etc. While Prolog passes many of my criteria, it doesn’t — in my opinion — pass criteria #8, as the learning curve for it is a lot higher.

    Anyone who wants to check out Prolog can download an excellent implementation called Visual Prolog. It provides an IDE with compiler, linker and debugger: you can explore Prolog’s logical, functional and Object Oriented features.

  15. Very good post!

    But doesn’t criteria #7 eliminates Scala? I understand your point about being on the JVM bring lots of library, but the language itself is not, IMHO, time-tested yet (but don’t get me wrong, I really like Scala…)

  16. I got a comment from someone calling himself “dynamic typer” who said that the compiler doesn’t add any more value if you have good unit (and acceptance) tests. He goes on to say “This post is actually a very good example of this fact: the trivial code example has a stupid off-by-one error that the compiler didn’t catch”

    There is no off-by-one bug in my code. Many people don’t realize that if you get back 1.5 times the money (say $1) you wagered, then $1 of that is your own money and you are ahead by only 50 cents and not 1.5. If you wager 1$ and get 3 times the money, you are ahead by $2.

    Regardless, it is safe to say that we are long way from the day when compilers are able to catch errors in application logic.

    Tests are important no matter the language that is used. All I am saying is that you will have to write more tests if you are using a dynamically typed language — and this should be taken into account when measuring productivity.

  17. Hi Babu, im one of the Lift core team – glad you are enjoying the framework and give Scala such high praise. I enjoyed reading your article and would like to add something that I feel has been overlooked; namely the ability for an enterprise to adopt a given platform or framework with their existing investments in infrastructure and hardware. This is where Lift (and Scala by proxy) have a great story to tell – a lot of enterprises already have significant investment in JVM-based infrastructure and as Lift just fits right in with its standards based systems it has quite an advantage over systems like django and rails that need either additional modules in an Apache build, or some custom server like Mongrel; this IMO, is a major selling point. Its certainly been my experience with both Scala and Lift that being based on a known technology (the JVM) has really helped gaining adoption into the enterprise space.

    Good luck with your adventures in Scala and Lift – hope to see you on the mailing list some time soon.

  18. Hi,

    Please take a look at HAXE http://haxe.org a “multiplatform language”. You can target javascript, php, as3, C++, NekoVM.

  19. My answer is Perl. See “Readable Perl” as slideshow or Readable Perl as pdf. Moose and Mouse help with OO Perl programming.

    As for Perl 6, is started after Python 3 and Python 3 was released not long ago. Parrot virtual machine is already at version 1.1. Perl 6 has regular releases – you can try it now, it has many libraries already. Wiki “November” is written in Perl 6.

    My favorite quote: “Amusing result for people who like bashing my favourite language… when i google for “Weird perl problem”, i get back 1,880,000 results… could be bad… except that ruby (2,000,000), python (2,030,000) and php (3,490,000) seem to be doing worse. perl may have weird bits in it, but it seems to have less than the competition… :) ” (c) ddick

  20. Alexandr, I have used Perl to write some neat programs. One that comes to mind is a Perl program that generates a Java TCK. Emacs had regular expressions before Perl. Perl is probably the first scripting language to have powerful regex built-in. It is a joy to use. Ruby (another Pe(a)rl), has been influenced by Perl. Many languages now have support for PCRE (Perl compatible regular expressions).

    I stand by what I said (good and bad) about Perl. No one can deny that the delay in releasing Perl6 has hurt it. Ironically, it gave a mini boost to Haskell as Audrey Tang used it to implement Perl6.

    Ruby and its author Matz were not known outside Japan until DHH unleashed RAILS and created a huge interest in Ruby. Python has benefited from Google’s embrace of it and that Guido works for Google. The rise in popularity of these 2 languages has had a negative impact on Perl.

  21. > It is likely that the number of volunteers is dwindling as they jump a sinking ship and go to Ruby or Python.

    I’ll give you all the other negatives about Perl, and Perl 6, but that last bit of speculation is pretty blind, in this age of clearly visible software repositories.

    http://www.ohloh.net/p/compare?metric=Contributors&project_0=Parrot&project_1=Rakudo+Perl

    That’s the activity of “Perl 6″ (Parrot + Rakudo) over the last years (That doesn’t include the pugs repo).

  22. I don’t think it’s sane to eliminate Perl because Perl 6 hasn’t been released yet. We should judge it on its current version – Perl 5. And all you really do to dismiss Perl 5 is to repeat the FUD that it’s line noise, without really backing it up at all.

    Don’t believe it’s FUD? Why are the likes of the BBC using it for something as important (and newly developed) as the iPlayer? Why is it trivial to find Perl (application) developer job postings from startups and established companies alike in many locations throughout the world? Are all these companies deliberatly looking to write obfuscated code?

    (And I haven’t said a thing about the vibrant community, recent developments such as Moose, which other languages are beginning to copy, strong testing culture that pre-dates even Java, etc, etc).

    Ultimiately, these sorts of discussions are purely subjective. If you think you can objectively choose the best overall language, you’re sadly misguided. I don’t think that’s what you were trying to do here, and I’m not even arguing Perl is the language you should have chosen, but at the very least, you could try to get your facts rights about the languages you’re discussing, instead of just repeating factoids that are easy to disprove.

  23. What a great article. Thank you! One thing that I would suggest that you cover is momentum. You say in a comment (this I think should be in the article) that python backed by google. That’s important. Which programming language do you think will be hot in 5-10 years?

  24. Adam, I don’t think my comment about perl6 being forever-ware is off the mark. Now it is slated for Spring 2010 — assuming that there are no delays.

    Patrick Michaud, the Rakudo Compiler Pumpking, has just announced that Perl 6 will be released in Spring 2010. It will not be complete, but it will be usable and useful. After all, people will only start using Perl 6 when it is “complete” (whatever that is – when will Perl 5 be complete?)
  25. Sam, If you read my article you will notice that I have sung praises of Perl. As I alluded to in one of my comments, I have written non-trivial programs in Perl — at a time when Python and Ruby were mere toy implementations. So I am not talking theory here. I have done a lot more programming in Perl than I have in Python or Ruby. Ruby owes a lot to Perl. Perl was one of the first languages to have the powerful regex package: so many other languages have copied it. I also said “There is a huge base of ‘legacy’ Perl software and Perl will be here for years to come.”.

    I also said “If you have invested 10 years in Perl or Lisp, you have a vested interest in defending it and you cannot be objective.” So I cannot expect you to be objective. I visited your blog and your header says “Perl programming, Open Source …”. The first article I see is “Why do people dislike Perl?

    The title of my article is “If you have to learn just one programming language”. Now, I am quite positive that if you do a formal or informal survey you are not going to find people picking or suggesting Perl as the language to learn — unless your day job requires it. You have admitted “I’m not even arguing Perl is the language you should have chosen”

    I mentioned in the article

    “All criteria except #10 are objective and measurable. #10 is to some extent subjective and therefore my bias will be reflected in the choice of language.”

    The thing that hurts Perl fanboys the most is when you tell them that their language is line-noise. I can understand that. So let me retract it and say that “Bad coders can write line noise in any language. If you follow good Perl practice you can indeed write beautiful and maintainable code in Perl”. Having said that, based on all the criteria that I selected, I would still eliminiate Perl — without, I hope, offending perlophiles.

    BTW, if I want to sing Perl’s praises I will pick something other than BBC’s iPlayer. You can read all about it via google search.

  26. I would have to say that the analysis of C# was not quite appropriate. F# does surpass it in functionality, but not focus. So your stated reasons for disgarding it were not quite valid. Your first reason was that “It never really took off”.. was not listed in your criteria for considering a language, and in fact it is above most of the other languages in the TIOBE index that you consider superior. And, yes, C# skills are in VERY high demand. Want facts? Look at the jobs boards. Learn Scala.. JUST Scala.. Good luck supporting yourself.

  27. Very nice article! Definitely enjoyed reading it. Too bad it seems the corporate world don’t really play by these criteria

  28. First of all, thank you for the comprehensive analysis.

    But, why drop Clojure just because of the paranthesis? Even old emacs and vi can take care of those paranthesis automatically and then we’re left with a very powerful and promising language: Clojure.

    Just take a look at this presentation: How a Clojure pet project turned into a full-blown cloud-computing web-app especially the page 61. Almost incidentally the page 69 says: Scala has no paranthesis which is why it is bloated with “syntactic sugar” :) And on page 79 you see the real beauty of Clojure: It’s got a built-in ability to draft html code. Lastly, it’s shown how seamlessly it works with JVM and Google App engine and that’s good news for Clojure, which is a rarely used language.

    I’ve got nothing to say against Scala, but given my basic knowledge of Common Lisp and the demonstrated usability of Clojure, my favorite language in the future is Clojure.

  29. I like the analysis. but i would like to add on the google GO.

    Go is based on the C programming family, one of the most widely used programming language trees in the world. However, the twist is that incorporates elements of PythonPythonPython (a preferred development language within Google) and the Pascal/Modula/Oberon family to make faster and more dynamic programs.

    but its new, so i guess it will not satisfy the author’s criteria of better compiler and development enviornment

  30. With V8 and node.js, JavaScript becomes a viable server-side technology, making it not only a universal client language (for mobile as well as general web development) but also as a fast, heavyweight computing language.

    I think your classification of it as an assembly-style language is misguided; Scala could easily be classified similarly if people were actually determined enough to generate it. JavaScript is beautiful because from within the language you can optimize arbitrarily, introspect and transform code with Lisp-style flexibility (see the Rebase project and the Divergence debugger if you don’t believe me :) ), and it, unlike Lisp, has a familiar syntax if you’re coming from the most popular languages.

    You can’t do this with Scala. Scala programmers are eagerly awaiting the release of the 2.8 production compiler, whereas in JavaScript one can simply create the features that are lacking. (Thanks to eval() and Function.toString primarily.)

    JavaScript is a vastly underexplored language. I think it would be premature to nix it if it is the case that, by your own admission, you haven’t yet learned it.

    Incidentally, anything you can do with the GWT you can do in pure JavaScript (but with the added benefit that your compilation platform is extensible). This can be compiled offline and then published.

  31. Bah, eliminating Clojure because of #8 (easy to learn) and #10 (readability) is harsh! I’ve been programming C, Java and Python for a while now (I’ve only been programming for 6 years) but I find the syntax of Clojure to be absolutely beatiful. You can even mix all sorts of symbols to make names, for example not= instead of !=. Isn’t that the pinnacle of readability? :)

    Don’t be put off Clojure just because of its syntax. You’ll learn to like it! Also, “code is data” is a feature!

  32. Perl line noise? That’s just silly. I read Perl every day that I haven’t written myself and it’s not harder than any other language. Of course you can write obfuscated code in it if you want, much like C or Java, but why would you other than the novelty value?

    The object syntax is too verbose but it’s not a deal breaker (and it’s pretty transparent what goes on underneath so once you get it, you get it). If you write new code you can choose a more modern syntax. That’s the reason Perl 6 is still vaporware, by the way, Perl 5 is still in active development.

    It’s simple, it’s pretty fast for an interpreted language (faster than Python and Ruby), it’s got pretty solid Unicode support (hardly any other has, except perhaps Python), and the massive amount of free code at CPAN is a life-saver.

    It still may not be the #1 language to learn if you should learn only one; In my opinion that would be C due to it’s universality and being only halfway-high-level so any structure and technique you learn is universally useful. But you count it out for all the wrong reasons.

  33. Thanks for the article, it was as well-written and in-depth as I could have hoped for. In fact, it cleared a lot up for me. I’ve seen a lot of these languages mentioned on social bookmarking sites, but never really took the time to find out that Clojure runs on the JVM and has Lisp syntax, for example.

    I have to say, the comments degraded into the sort of dick-swinging, alpha-nerd, overtly defensive, pointless one-upmanship that makes me want to abandon software development.

  34. I bow down to your total and complete nerdieness! You are lord of the nerds.

  35. Hi Babu,

    Interesting analysis, thanks. I agree with the second commenter: not only should have Fan been in your list but I think it would end up in the top two with Scala (and personally, I would pick Fan over Scala).

    – Cedric

  36. Nice analysis. I agree with most of it, though I would say that C# is in much more demand than you might think. Practically all jobs I see in the paper is C# or Java, but C# is mainly used in the enterprise.

    While I agree with Scala as a winner, it is not the easiest language to learn. Compared to for example Python, it will take a bit longer time to do much useful.

  37. I’d like to know how Lua is labeled a niche gaming language, when 40% of adobe lightroom is written in it. Isn’t that what criteria #4 is all about, a scripting language that does double duty as an application language?

  38. This blog post is breathtaking in its comprehensiveness. I promptly reblogged it.

  39. I don’t think the argument for dynamic typing is it’s easier to just not specify types.

    To me, the advantage is that you don’t end up with insane interface pollution…. i.e., interfaces everywhere, by the hundreds, one for every method that wants to accept multiple different kinds of objects.

    In Ruby, you can print any object that has a .to_s method. You don’t have to create a Stringable interface, and all those objects don’t have to inherit from String. Just implement .to_s and throw it in there.

    To me, that’s the big win.

  40. Nice post. I was under the impression that while the JVM does not do tail call optimization, the Scala compiler does.

    Having taken the time to learn Scala myself, I’m pretty happy with it. Its also nice seeing more momentum with its uptake and the number of open source projects starting that are implemented in Scala.

    I still think its too early to tell if it will unseat Java in terms of new (enterprise) project numbers (its nowhere near that point now). I think much of that will depend on when Java 7 is released and reaction to it.

  41. Good post!

    I do have a remark though, which is about OCAML (and JOCAML). Although the syntax is a bit awkward, the same holds for any ‘species’ of programming language you’ll learn. I remember that my first Basic (in the early 80′s) experience included getting used to the strange syntax, just as my first assembly, prolog, lisp, C/C++/Java, Haskell, Python and OCAML experience. Just because someone is used to a certain syntax doesn’t mean that other syntax can’t be good either (I prefer Python and Haskell, although that also take time to get used to). After a while most ‘weird’ syntax issues disappear once a person starts to think in the logic of the language, and not the syntax (although I never got used to LISP, but that is something VERY personal, and not a reason not to recommend it).

    OCAML has a really good performance (close to C) but is high level. It can be used for functional and imperative programming and has classes.

    The reason for the ‘+’ and the ‘+.’ is because it is so strongly typed that the compiler has different optimizations for integers and real numbers, which after thinking about it makes sense. Integers are often only used for counting (in arrays etc), and reals for the more advanced mathematics.

    Please have another look at OCAML. Especially with the JOCAML it is muticore functional programming at its best. No wonder that Microsoft based F# on OCAML. :-)

  42. Excellent post! I generally agree with your conclusion but, for me, there are a few features of Erlang that weigh heavily. They are Erlang’s built-in ASN.1 and bitstring support. I often have to work with binary streams. The on-the-wire structure is sometimes home-grown and other times outside forces have chosen ASN.1 with a specific encoding rule set. In both cases Erlang’s abilities in these areas shine.

  43. …It would also be interesting to see the above article rendered in non-programmer terms for newbies. Judging from the level of most of the reader comments though, I may be alone in wishing for that. I have since done a little reading on Scala though. This article inspired that.

    Thanks Babu!

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>