Thanks for the essay. Nice to see someone take the attitude of "This will get me flamed, but here's what I honestly think."
My question is, what speed difference did you see between your Java and C++ implementations? People always say Java is slower, and I know it used to be. But while optimizing a math-heavy Java program recently I tried rewriting it in C and was surprised to see only about a 20% gain. Aside from the lag when starting up a Java program, what performance difference have you found between it and C++ or C? There are many conflicting benchmark results out there but one often smells a bias.
I'm trying to choose between Ruby and Python myself for quite some time now. Thank you for this article.
But for me the biggest issue is availability of 3rd party libraries. I would like to hear others' experience on this.
I program mostly in C++, but sometimes I just want to cry when I try to find a C++ library for some specific functionality and I find zillion Java libraries, some of them famous and half of them free, and total of three C/C++ libraries, all of them commercial.
On the topic of speed, I often compare things with my Java friends. My (biased) conclusion is that Java comes near the C++ speed only in brute math tasks or similar. When you try e.g. parsing of large xml files, working with large recordsets, desktop gui showing much data and refreshes constanly etc - with Java you are either dead or nead a $$$ server to run it on.
But I also noticed it might well be because of a human factor: people that program Java, often don't consider performance at all during design, maybe Java unintentionaly encourages that approach (like VB encourages spagetti-coding)?!
lack of multiline comments in Python/Ruby was annoying
Python has had multiline comments for years. Indeed it is a staple of the documentation tools.
""" This is a multiline comment """
Now perhaps Ruby does not have them. But if so, you should explicitly state that Ruby doe snto have them. Don't tar Python with that brush because of Ruby.
Oh, I am delighted that I'm not the only one that sees the runtime _only_ type checking of python as a problem. I can attest you from experience that it's very prone to runtime breakage in large programs. Unit tests don't help, because they have to be written by a human. Instead of writing unit tests I could as easily (or easier) just add some type names here and there if the language allowed it. This is the bane of python. However, Guido Van Rossum is aware of the problem and there is a discussion underway.
And there is boo, too :) http://boo.codehaus.org/ it's like python but _with_ optional static type checking and type inference.
As for C++ STL, you like it, really? They always were my biggest critic point in C++. From a pragmatic standpoint they are as bad as it gets. No decent string operations, no parser (lexer) classes, "global" functions scattered all over the place instead of more sane member functions (find, copy, anyone?) - and I don't care about if their implementation was easier to write that way. I care about the interface and that is bad. Aproros interface, no interface types, no Components model (COM/Corba/dbus) and _no way to add it via RTTI either_. Oh yes, no RTTI. No decent namespaces (only as an afterthought and not usable). Hand-Written iterator classes instead of yield / generator pattern. Ever tried std::transform tolower? Needs a cast of the ctype tolower() function although the prototype looks ok and _works_ after casting...
Then one is supposed to do manual memory management but the container classes when used with pointers as items do not free the memory these point to. Trying to use non-pointer item in a container class gives rise to error messages so unreadable that I could understand Klingon better (and I can't understand it at all). auto_ptr. Need I say more?
Great article. Interesting to see I'm not the only one struggling with the Java vs Python vs Ruby question. It's a tough decision.
I agree with your comments on C++. But STL, I really didn't like it. I think these days people really only do use C++ if they have to! :)
It's tempting to stick with Java and forget Ruby/Python, but coding in all the extraneous crap that you have with Java is a bit depressing.
In my evaluations I did a similar exercise to yourself and compared Perl, Python, Java, Ruby, PHP5. I really liked Perl funnily enough. However, like you I didn't reach any real clear decision over Python/Ruby/Java. In pure language terms I probably liked Ruby best. But there are some things I like about Python. Java also has some major strengths, with it's great libraries especially Swing. Very frustrating as I couldn't reach a clear decision about which one to really pump the time into!
I guess ultimately it's the application that will dictate the best language..
You got the speed thing as a usually premature optimization, but missed the point about the testing. its not 'testing for type correctness', its testing for correctness, full stop. In dynamic languages like Python, variables can be associated with more than one type in the life of a program. I know, this can seem weird to a static typing aware programmer, but when you start to use a dynamic language like Python idiomatically, you can take advantage of a very powerful technique called 'Duck typing' (http://en.wikipedia.org/wiki/Duck_typing)
Touching on speed again. Python's conciseness, readability, and interpreter, optimise speed of development and maintenance over languages like C++ and Java. Because you were porting a program between languages, this aspect may not have been revealed.
- Paddy.
P.S. Pythons doctest module allows you to effortlessly take the 'scriblings' you might do in the interpreter whilst creating a class and turn them into unit tests: http://en.wikipedia.org/wiki/Doctest
I personally (and maybe I'm the only one) think Ruby's syntax is awful and hard to read in a lot of ways.
Some of the conventions Python takes on seem to be more effective to me, but I am not reasonably experienced at either. I totally agree about the multi-line comments though.
One thing I would consider is something like Jython (a Java compiler for the Python language). It seems to be a pretty effective way of using Python for productivity and gaining many the benefits of Java.
On the Java vs. C++ performance issue, I have noticed less and less a difference over the years. I wish I had a link, but I have found several reports in the past showing that most of the speed differences that exist now are the result of Java's array bounds checks, a stability / security issue. Just a thought.
Dave, thanks for a great comparison article, and for using a clear proven example,
You've made me seriously consider dropping Python for Ruby. That explicit 'self' is a pain. But other comments mention boo, which may be more useful in the end, with the ability to do type checking.
Optimising for speed? There are only three rules to remember, said my programming guru, Peter Juliff, way back in 1979 (!): (1) Don't do it. (2) Don't do it. (3) Don't do it yet.
* There is a lot of duplication in the private methods. It really could be factored out (that goes for the other languages too) * Needs copy constructor and assignment: The pointer members will almost certainly break without proper copy methods defined, or declared private (and not defined)
* The public constructor should probably be declared explicit * A default constructor would probably be good -- STL classes usually have one
* Put public methods first in a class * Limit file to 80 chars per line (fit on web pages, etc., better) * Method implementations inside class declaration mean the compiler will (try to) inline. Is that really wanted? (not if it bulks-up the exe unnecessarily) * Stroustrup and Meyer suggest "Type* name" rather than "Type *name" since the embellishment is part of the type * Some method names are not verb-ish
In return I can put a couple of my own dual-language implementations in the firing line:
I quite like the article, its written in a very unbiased way.
I'm not a fan of ruby, its syntax is quite ambiguous in feel, it feels like its so open ended, I could get something wrong easily and never notice. Python doesn't have that approach, it looks clean, and uses the consistant ":" for almost everything. However, I haven't used much Ruby and I'm slightly biased.
Theres allot I could say about C++. Between all of the languages, C++ is the only language that gives the programmer great amounts of flexibility in design while sustaining its speed at runtime. Indeed, C++ feels more complex than the other languages, but I keel that over by just "getting it done". To a noob, C++ is probably not you're friend. To a Pro, C++ can be your best friend, as you gain experience, most of those runtime errors that used to plague you dissapear. C++ also becomes allot easier when you use Boost libraries, which make so many idioms a hell of allot simpler.
I agree with you that c++ should be used when speed is a requirement, it being the fastest of all the languages. I have a need for speed more than others, so I tend to write lots of c++.
However, overall my language of choice is python. Python has the best "standard" library of any language. Everything other than niche libraries are included twith standard python, I can get 99% of what I need to achieve with the standard python library distributed with almost every python implementation. Python is convienent and productive to write in as well.
As for Danny Milosavljevic, His comments are wrong. C++ *has* RTTI, in the form of typeid, and dynamic_cast. As well, C++ has usable, workable namespaces. The standard algorithms are globall functions not because its easier to implement, but because its more intuitive and flexible. Those same algorithms work on pointer types, and home made classes and iterators (I've done this more than once). As well, using auto_ptr in a container is a dumbass idea to anyone who knows c++ well. auto_ptr isn't copiable, and thats a standard requirement for containers. And, the reason that containers holding pointers don't delete what they store is because they can't determine ownership. More than once I would have died if containers deleted their pointers, it would have been symantically incorrect and forced me to take a harder approach.
You said: "My general feeling was that Python annoyed me in ways that Ruby didn't, but I think those annoyances would disappear if I was using Python all the time."
Well, I tried using Python a lot, and the annoyances got more annoying, especially if you also are writing code in other languages.
The worst thing about Python is the invisible dedent. Two dedents look like one, depending on your choice of indentation. An indent is always a single indent, no matter the width. Yet, this is one of Python's most touted feature/bug. A Python-aware editor helps, but the same is true for fixed-form Fortran77.
So, if Ruby and Python are about the same, the choice should be on your preference for coding style. Some people like Python's style; I hate it.
It seems rather lame to pick a language based on coding style rather than syntax and functionality. Python would be a clear winner (to me) if it supported an alternative style.
You said: "My general feeling was that Python annoyed me in ways that Ruby didn't, but I think those annoyances would disappear if I was using Python all the time."
Well, I tried using Python a lot, and the annoyances got more annoying, especially if you also are writing code in other languages.
The worst thing about Python is the invisible dedent. Two dedents look like one, depending on your choice of indentation. An indent is always a single indent, no matter the width. Yet, this is one of Python's most touted feature/bug. A Python-aware editor helps, but the same is true for fixed-form Fortran77.
So, if Ruby and Python are about the same, the choice should be on your preference for coding style. Some people like Python's style; I hate it.
It seems rather lame to pick a language based on coding style rather than syntax and functionality. Python would be a clear winner (to me) if it supported an alternative style.
Ruby is a clean powerful languige that is slower but more powerful than any other populer languige. ruby has good suport for the functional stile using blocks and iterators
This is certainly not good Ruby style. You should do
class RedBlackTree2 < Struct.new(:val, :left, :right, :color)
So you'll get copy, accessors etc for free.
Another example:
def find(key) result = nil if (key == @val) then result = self elsif (key < @val) then result = @left.find(key) unless left.nil? else result = @right.find(key) unless right.nil? end return result end
should be:
def find(key) if key == @val result = self else leaf = (key < @val) ? @left : @right leaf.find(key) unless leaf.nil? end end
Interesting post. I'm pretty much a Ruby convert these days, coming via Java from a strict C/assembler background.
I never did like C++. Always seemed like objects bolted onto C. The syntax groans under the weight of all those overloaded keywords - in particular, you seem to be able to slap a "const" just about anywhere in a definition / declaration.
I love Ruby but I appreciate that Python is slightly more mature and able to do pretty much all the same things as Ruby, but I find Python's syntax sickeningly reminiscent of Cobol (all that indentation). Also, really really useful things like generator functions are so much easier in Ruby.
However even Ruby has drawbacks - yes, the error reporting is abysmal, and like you I find aspects of the syntax arbitrarily ill-conceived (my pet hate is the stupid case/when construct - what's wrong with switch/case?!!).
Perhaps the winning language will be just like Ruby but with curly braces instead of begin-end, and all those other funnies standardised?
You mention that dynamic typing is a huge productivity gain. Can you eloborate on that ? Is that because the code is less verbose, or because it alleviates the need for compilation ?
dynamic typing is a productivity win ... at the cost of some risk
I think that the point is ill-posed: what really matters is the average number of unnoticed errors after testing. With static typing you know a priori that there will be no errors of a certain class: but how can you infer from this that total number of errors will be smaller?
Given the same programmer, there is no doubt that in Java with stronger type checking there will be less errors than in Java with sloppy type checking. However is class and number of coding errors invariant with respect to the programming language adopted?
What one really needs is experimental or psycological evidence that static type checking makes unnoticed coding errors less frequent.
I am an experimenter of languages in Bioinformatics domain.
My Rating of programming languages in Bioinformatics domain is :
Java > Perl ~ PHP > C/C++ >Python.
Microsoft languages are out of race. (As u know platform issues)
I think a big conspiracy is happening to null Java because all the famous writers of Java are now moving to Python/Ruby. May be they are lured by bigger corporations which use Python along with their propreitory languages.
But as you will see soon in the coming years, Solaris OS will dominate and Java packages for task optimization will capture market.
Let me tell u simple reasons why Java's best:
1) python and ruby can't handle mouse events for complex graphical applications that load on a web page. ( Meaning u can't drag a cubic spline on a web page and at the same time change values) PHP(Applet) and Perl (For windows due to Tk plugin) can achieve this partially.
2)In PHP you can never tell how many bytes of a file have been transferred to the server when you try to make file uploads.
3) In Perl you can do everything but writing secure web apps and support for OPENGL is not easy. Writing molecular modeling tools requires good supporting libraries. Also server side image mouse events is yet to be achieved with relevant plug-in that works for all browsers like Java.
4) Python is wonderful for standalone applications but web application development can be nightmare for new users. Using Pyrex also doesn't improve speed.
5) Ruby is no good when it comes to graphics. Also to add AJAX, JSON are not the only things that are highly important in web apps.
6) Finally looks like programmers may want C++ Server pages with no pointers. (Security)
7) I agree that opinions & choices vary from one domain to other but remember Bioinformatics is the place where you tend to stretch the capabilities of languages most due to complexity of problems.
Just a comment on why Ruby uses "begin/rescue/ensure" and not "try/catch/throw". Ruby has "catch/throw" in the language but for a different purpose, to escape nested loops much in the way you would use flags and break statements for (or named loops) in other languages. For example rather than:
flag = 0 while(true) { while(true) { if(a) { flag = 1; } if(flag) break; } if(flag) break; }
You could do:
catch :flag do loop do loop do if a then throw :flag end end end end
Just thought you might be interested in that tidbit as I just found this out.
I'm currently using Ruby for a mostly academic project because I like its flexibility/syntax more than Python but I think if I were going with a bigger more production project I'd use Python because it has a larger community/more readily accessible and stable modules.
Thankyou very much for this nice over view of four languages. I really found Python/Ruby part very interesting, as I have been to jump on this band-wangon too after years of Javalisation! So far, I can't make a clear choice about which way to go: Python or Ruby. Although I really like Ruby syntax and OO Completeness but Python seems to have more tools availble for various purposes..
I would argue that other big steps forward for Java are: A consistent error reporting model and the ease of creation of libraries (C++ focused on ease of use of libraries, but creating them was still hard. We can see the results in far more Java libraries).
In my experience Python is pretty darn fast much of the time.
The fact that Sun is directly supporting JRuby development is very interesting. I could easily see a future where JRuby is the top-level language that makes use of Java components. Rather than writing everything in Java.
Thank you for the essay. What I miss in the comments sofar - or is it so obvious to everybody? - is that it usually boils down to 'the right tool for the right job'.
I realize that the Red/Black tree was used as an example on how code looks, not as a serious implementation, but it's still deeply rooted in the C/C++ domain. Fact is that the Python code was mostly C++ code ported into Python, and not a Pythonic solution for the problem - but then again, why bother with the tree - I'd probably use a dictionary in the first place. I can only assume that the same applies to other languages. And the example fails in that aspect in the pay-off for performance loss of Python/Ruby compared to C++: code that is much, much shorter (and, assuming equal proficiency of the languages, probably much easier to understand)
Type checking? I miss it in Python, because I'm so used to it - but most of my Python scripts are so simple that they don't need type checking. Recently I had to convert around 1000 graphic files from one format into another. The only batch converter that was available could only handle one directory at a time and my files were spread out over 100s of directories. A Python script that renamed them, copied them to a single folder (had them batch processed) and copied & renamed them back was written and executed in less than 30 minutes. Using C or C++ for a task like that didn't even come up in my mind.
On the other hand (warning: flame alert) scripting my Excel spreadsheets with Python would be overly complicated - it's much easier to use the built-in VBA for that. And as while Python performs excellent in a product as Spambayes, I would still be very distrustfull of the performance of a spreadsheet or database server written entirely in Python - C++ gives much better performance for that kind of software. And that makes is so hard to compare different languages with each other - inside their domain their hard to beat, outside they're a lame duck.
Oh, and "Bioinformatics is the place where you tend to stretch the capabilities of languages most due to complexity of problems" - I don't buy that as proof that Java would be 'best'. If it were, all supercomputers would be programmed in Java, and they aren't.
One other commenter raised the point that red-black trees are usually used to implement what associative arrays, also called dicts in Python and hashes(?) in Ruby. You then go on to state that Java and C++ are much faster than the dynamic languages. The dynamic languages, especially python, rely heavily on the speed of their dicts. The code implementing Python dicts is highly optimised. A different speed test would be to pit red-black tree implementations in java and C++ versus native dicts/hashes in Python and Ruby, to store N trees/dicts/hashes as the items of another tree/dict/hash; where the N subtrees/dicts/hashes contain M different integers.
Set N and M to around 1000 and compare performance.
Look at the code for the implementations.
You would probably find the dynamic solutions to be a few tens of lines of code, and the static anguage examples several hundred lines of code. The Python/Ruby examples would be created in 30 minutes and a doddle to test. I doubt anyone would want to complete the Java or C++ example as part of a blog post. It would take too long, except if they employed an *external* library.
On the explicit-static typing verses dynamic typing issue, I'd love to have the advantages of type checking without having to add type annotations to my program - inferred typing? But even then, it would need to allow duck-typing. - Paddy.
One other commenter raised the point that red-black trees are usually used to implement what associative arrays, also called dicts in Python and hashes(?) in Ruby. You then go on to state that Java and C++ are much faster than the dynamic languages. The dynamic languages, especially python, rely heavily on the speed of their dicts. The code implementing Python dicts is highly optimised. A different speed test would be to pit red-black tree implementations in java and C++ versus native dicts/hashes in Python and Ruby, to store N trees/dicts/hashes as the items of another tree/dict/hash; where the N subtrees/dicts/hashes contain M different integers.
Set N and M to around 1000 and compare performance.
Look at the code for the implementations.
You would probably find the dynamic solutions to be a few tens of lines of code, and the static anguage examples several hundred lines of code. The Python/Ruby examples would be created in 30 minutes and a doddle to test. I doubt anyone would want to complete the Java or C++ example as part of a blog post. It would take too long, except if they employed an *external* library.
On the explicit-static typing verses dynamic typing issue, I'd love to have the advantages of type checking without having to add type annotations to my program - inferred typing? But even then, it would need to allow duck-typing. - Paddy.
Good article. I can tell you know what you are doing because you are using jEdit. :)
I think there is an advantage of Java that is left off in this article. That advantage is that Java libraries can be learned and utilized faster because return types from methods (or functions) are discoverable in the API documentation for a library.
That may seem like a minor point and it would be to someone implementing a low level algorithm like a red-black tree because you didn't use any third party libraries. However, I think the main advantage of java is all of the ways in allows us to reuse libraries written by others. Java in that case can be quite efficient because it allows us to understand and reuse someone's library quickly and that's a major gain in terms of productivity for me.
I think that the ease of library integration is of great concern for a high level language.
I would argue that, since several of the posted code examples are not good representations of the expected style of each language, the assertions about the languages may be invalid.
EG. Suggesting that dynamic typing is a huge productivity win certainly can't be based on lines of code when the languages aren't used appropriately.
Java's toString() as it should be return '[' + __val.toString() + ',' + __color + ']';
Instead the article uses 3 lines for java. There are others but this just illustrates that revised versions from language experts should be produced and a follow-up written. The assertion are _likely_ to still be valid, but at least they'll also be based on valid data.
NB: I'd also like to see timing data giving us a measure of statements such as "C++ is way faster than java" - I expect it is, despite being in favour of java and being aware that many evangelists will point to other test data as counter-arguments. I'd just like to see the assertions made here backed up with numbers.
Thanks for your very interesting analysis ! I'm a Python coder with a background in C, C++ and Java (which I still use often) I know I'm quite late ;) but... what about Pascal derivatives ? http://www.freepascal.org for example. Modern Pascal, in my opinion, could be still useful in some circumstances. It's a bit verbose but for sure fast and maybe a bit less messy than C++. Or its time is over ?
The Java code should not contain the underscores __x__. It is one of the advantages of Java that you don't have to play this trick to achieve private naming.
Recently I was determined to pick from Python and Ruby for a project I'm going to work on. I tried with each. This far I'm convinced that Ruby is the way to go.
I haven't been much of a developer until recently. I've started with C a few years ago, but didn't want to move with C++. I never liked Java much. I know it's a great language. And it's mere capabilities have hold me in awe. But the speed was always bothering me (perhaps I used my old computer too much).
The most annoying things about Python was indent based block defining, which I felt uncomfortable to rely on. Knowing that one 'tab' press was enough to create trouble wasn't easy, especially when I'm using 'tab' key extensively on Linux. :) I know I haven't used Python that much, so I tend to be uncomfortable using Python. Learning that Metasploit project chose Ruby over Python was also not helping. :)
Ruby on the other hand seems well designed and cool and easier to learn. And it felt lot better than Java.
Perhaps what I read in an article was true. That Python was a good language which came out in a wrong time, so now it's the time of Ruby.
Really interesting article -- can't find many objective comparisons of these languages.
I'd like to share a few notes, particularly on the C++ implementation:
- I disagree about treating of built-in types and class types being harder in C++. I actually think it's easier in C++, which supports real POD types and therefore doesn't require things like extraneous casts or boxing/unboxing.
- Similarly, there are good ways to generically convert something to a string: either ostringstream (flexible) or boost::lexical_cast (concise). Overloading operator<< first if you've got a custom type.
- I'm not sure what IntNodeVisitor was introduced for, but it's unneccesary. Just fold the visit method back into NodeVisitor. If you did need to customize your implementation based on type (which you don't in your example), template specialization would be the way to go.
- delete 0; is a valid nop in C++ so you don't need to guard against it.
- Most C++ coders use (!a) instead of (a != 0) and similar, and omit {}'s on single line ifs, which would both serve to reduce clutter a bit.
Personally I love strong static typing, it does catch more errors earlier. I wouldn't try to do anything enterprise-class without it.
I absolutely agree about the utility of garbage collectors, first class functions and lambda expressions. They are real productivity boosts. And I'm the first to admit that C++ is a harder language in general.
I am not going to develop very much my comment but I think C++ and java are a step ahead: - IDE and tools support. - libraries. PDF, excel, reports, imaging, net, ws-*, xml, etc. - java code readiness, imho is quite clear. Scripting languages tend to be tricky soon of you are not ver very carefull. - static typing. Dynamic is ok if you are a good programmer, but the average might prefer to focus on some more important issues. static also helps you on maintainability as well (distinct developers on the same piece of code). - Java c++ general purpose. this could not be a strength but i feel java/c++ a more complete platform.
I'ts harder for me to find a productivity gain from python/ruby (on Rails????) on real projects since small ones tend to be quite similar independently of the technology you use.
I prefer java as you could see here but I am not a fan(atic).
I programmed for a decade in C++ and several years in scripting languages.
The thing about the scripting languages is that any library worth a damn is written in C. But there comes the downfall in that the availability of said library on the various platforms is a hit or miss affair. And woe to those that have to write such a library and make it available on most platforms.
Then I got into Java and consuming libraries from a vast reservoir of open source libraries was a breeze. It was a characteristic of Java I noted from day one - it really kicked serious ass over all other languages in terms of libraries available for it. Plus creating the libraries could be done in Java itself - while still being adequate for real world use. Naturally the platform problem was then a non-issue for said Java-based libraries.
Finally I've now come circling back around to scripting languages via a variant of JavaScript, called ActionScript 3. Yes, the programming language of Adobe Flex 2.
So what have they done to JavaScript - which is a functional and a dynamicaly typed language?
Well, in ActionScript 3 they've evolved JavaScript to the point it's very, very close to Java in many respects.
Also, the default mode of the Flex compiler is to enforce strict, static typing, as it's considered the preferred way to program in ActionScript. As added enticement to lure the dynamic script language junkies, they're told that in the Flex Builder IDE the strict typing approach to writing ActionScript will enable them to use this wonderful feature called code completion, which will greatly assist their productivity.
Yes, the irony is several miles deep here.
The dark little secret is that the script language crowd covet the many benefits of static typing - especially as they get immersed in projects of greater complexity and multi-team complexion.
These days I relegate a script language approach to one-off utilities and test code. Or as a means to add programmability to a running application, such as embedding Rhino or Groovy in a Java program.
The industrial strength, production code is still being written in Java, and there's just no serious contender to be a suitable replacement in sight. Yet.
Your article is very well written and very balanced in its arguments. My thoughts:
On speed, look at this site:
http://www.timestretch.com/FractalBenchmark.html
The author uses a mandelbrot program in various languages as a speed test. Heavy numerical crunching here. you will see that Java is actually very fast compared to Python and Ruby, due to its JIT--Just-in-time compiler. Several dynamically typed languages, including Lua, have JIT projects underway. Ruby 2.0, coming in 2008, will be at least as fast as Python, based on current benchmarks for the developmental Ruby 1.9, which give Ruby a threefold speed increase. This will help Ruby greatly.
Notice in this test that compiled OCaml, is as fast as C. Objective CAML is a functionally based language, with added imperative workings and object orientation. Notably, it has strong, static typing,but, all types are inferred, so you do not have to type the type names. With OCaml, you can have your cake and eat it too--except that syntactically it is challenging for the non-functional programmer.
I have programmed much java and find it relentlesly verbose. I have used Python and am now exploring Ruby. I find Ruby to be even more compact than Python, and yet still readable.
Another issue for comparison of dynamically typed lans and Java versus C++ and other compiled langs is the issue of deployment--how to package up an interpreter or JVM with your code so the user does not have to go and install something on their system.There are some solutions for this like py2exe, but it is definitely as issue for non-compiled languages.
The memory leak problem could be solved easily by smart pointer, auto_ptr. Moreover, the structure of RB tree is highly symmetric so that it's possible to merge opLeft() and opRight() into op() staticly by function template.
Nice article. I've been programming since 1976. I've gone through all of the simple and standard languages, BASIC, Assembly, hand-coded machine language, C, Pascal and cruised through C++, Java, LISP, Python and Lua. I've looked at Ruby, considered that it was close enough to Python and Lua that I didn't need to learn another one.
For the time-being, I've settled on Python as my main language, dipping down to C as required. Here are the languages that I feel are most comfortable and productive:
Python C LISP
I have a few issues with Python. The indentation for blocks was a little strange at first, but I found that it has two advantages. (1) It creates very readable code and (2) Most people don't realize this, but I'm pretty sure the indentation for blocks evolved out of the usefulness of this when you are truly using it in compiled mode. When using a CLI such as IPython or the Python shell itself, it's very natural to use indentation to handle blocks as the CR ends the last semantic block and will likely execute the block of code you just entered. I hope this makes sense.
Having been forced to program in Java again, I've noticed how often I need to go back to the reference manual to get around unnaturalness issues. Things that are simple should be simple. Things that are complex should be doable. You should also be able to keep a basic core idiomatic functionality in your head which translates directly into useful code.
For example, you're debugging and you need to find out why the values that you're getting aren't correct. You toss in a few debugging statements. In python thats 'print'. In C that's 'printf'. In Java that's... System.out.println(some concatenated strings). Ooops. I needed to print an integer. Crap, grab the manual, how do I do that? Now I know you can use alternate interfaces to achieve the same thing, but again productivity.
Productive programming comes to a stop.
Here's another. Two strings, A and B.
Let's do the simplicity test:
(BASIC ;-)
IF A=B THEN
C:
if (strcmp(A,B)) {
Python:
IF A==B
Java:
if A.equals(B)
Okay, C isn't so natural because its a high-level macro assembler and we can excuse that, but even BASIC gave you a readble string comparison. Python does it nicely. Java bows to correctness instead of productivity.
Java's automagic garbage collection. Nice, but hardly new. LISP had garbage collection 40 years ago.
Here is my bitch about Java. The amount of syntactic and semantic cruft needed to do anything straightforward and the excessive obsession of the Java community in general to wallow in playing OO games to do what anyone else can do in C or Python in less code and much more directly.
In other words, spending 10x the amount of time discussion the intracacies of J2EE, Beans, Spring ad infinitum rather than getting stuff done.
And that's what it comes down to. A tool that helps us get stuff done cleanly, quickly and maintainably without the obsession with the tool itself.
(Don't even get me started with my experiment in sending UDP packets in Java. I had to coerce a buffer through 5 different types before I got what I wanted). Total time to make it work. 3 - 4 days of looking stuff up and going through class documentation. In python I did the same thing in 2 hours from scratch.
Postscript:
In terms of the next great language, I think we should be looking more seriously at D. It's a true compiler, designed by the author of the Zortech compiler which removes the problems of C++ and Java while retaining a clean OO structure and not forcing us into someone's proprietary VM structure.
In other words a true systems OO language that is powerful, compiled and doesn't straight-jacket us. Hop on board the D train.
I had to choose Python over Ruby because of i18n and l10n. Otherwise, I find Ruby more pleasing to code. Moreover Python beats Java, C++, and Ruby in i18n and l10n.
It would be interesting to include Microsoft's C#. My experience has been that C# is much like Java in terms of developer productivity and runs as fast as C++ code.
I feel like some of the issues here are a bit mixed up. I saw execution speed, syntax, garbage collection, OO consistency, type system, and the killer "productivity".
I'll rule out execution speed and productivity from my post because:
-> Execution speed is orthogonal to all other issues: overall, a languages isn't fast or slow. It's available implementations are. As an example, DrGB noted that compiled Ocaml is about as fast as C. But the bytecode is way slower.
-> Productivity is a consequence of the rest (except execution speed). The more, the better. Now, the real question is: how language design influences productivity?
Let's start by syntax. At first sight, the quality of the syntax can only influence productivity by a constant factor. It is largely a question of taste, habits, whatever. A notable exception is customizable syntaxes, introduced by Lisp. With these, one can set up a domain specific syntax, and shorten the program with that. We have here our first Holy War: rich syntax vs (almost) no syntax. A rich syntax is readily more readable, but not easily customizable. This is (very) roughly the difference between having "foreach" provided by Sun, or building it yourself.
Garbage collection. Well, it looks like everyone here agree that a garbage collector reduces burden, and increases safety. Both effects increase productivity. I will add that performance is roughly unaffected by it (contrived examples aside).
OO consistency. I don't know much about OO, so take the following with a grain of salt. I just feel that if each value in a program is an object, whose class inherits from some "root" class, life is better: genericity comes for free, and polymorphism can be used more pervasively.
The type system. This is our second Holy War. Basically, we have four of them: -> none at all: C -> Static, manifestly typed : Java, C++ (to some extent) -> Hindley-Milner. (ML derivatives, Haskell...) -> Dynamic type systems (Python, Ruby, Lisp...)
The problem I see here is that many posts here sound like: "Ruby is more productive than Java, so a dynamic type system is likely to be more productive than a static type system". I disagree with that reasoning: First, Java and Ruby are too different to draw this kind of conclusion. Second, we have more than one static type system at our disposal. See here a (angry) post which illustrate my point.
The trade-of is easily stated: a static type system doesn't let us built collections of objects of different types, and a dynamic type system catches type errors at run-time rather than at compile time. Consequence: a static type system requires more workarounds, and a dynamic type system requires more tests. I think the way this affects productivity is far from obvious. (Well, I have two exceptions at hand: throwaway code, and "Earth-is-doomed-if-I-fail" code)
We are conducting a similar study based on the popularity of Python vs Ruby, Perl, and Python. You can see what we found out at http://www.odinjobs.com/blogs/page/careers
So my question is, how maintainable are these languages for large scale production environments? Which ones are better for operational efficiency? How does Lisp compare?
I made some kind of comparison. I have implemented the "payroll" application from "Agile Software Development" in ruby. It took me 10 times less LOC than the author wrote it. Great isn' it.
And about maintainability: I started the whole in oktober. I stopped developing it for a 2.5 month. This week I continued developing and getting into the code was without any headache.
Here is my post about it: http://orbanbotond.blogspot.com/2008/01/ruby-on-rails-productivity.html
I´ve read through all the comments here as well too get a "feel".
I must admit i´ve been a little curious about Ruby & co after all the buzz lately.
I coded a little C way back, but got bitten by the Java bug maybe 8 years ago. Last year i been working with .NET/C# and ajax. (Witch is also nice I think. It´s very much like java but without the community, the high quality open source libraries and also the platform dependent thing of course. Although very nice debugger, ok for GUI coding, and good integration with the (win-)OS)
I think all languages mentioned have their shining areas. C/C++ is a must for low level coding. (started with hardware integration , circuits design and robotics lately, so will bee doing a lot more of that now) In my opinion PHP, Ruby and Python is very well suited for getting smaller applications or protypes up and running. (Maybe ASP.NET comes in here as well)
Dynamic vs. Statically typed languages thats the question, you say?
Well i mainly create enterprise applications so i better be dame sure it´s up and running 24/7 with the minimum amount of errors and preforms well. Do i dare user dynamic typed, not so sure. It´s like using AJAX in highly critical applications. Goes well MOST of the time.. :-S (i use it a lot, but not for highly critical areas. Ever seen a 100% bullet proof javascript (witch is client side dynamicly typed by the way;) )
...I think the most important, i my eyes, is to remember the language is just a tool! Know your tools well so you can focus on what really matters. The business logic, and/or algorithms.
I don´t code 10000 lines of code a day. I spend a lot of time thinking , planning and discussing business processes too. I spend a lot more time coding in C# then I would have in Java because i know Java better. But I understands the concepts and get there after little extra effort. What sometimes really take time is find the errors that only reveal themself in the production environment etc.
Personally i think it would take many years coding eg. Phyton to get at the skill level I´m now in Java. So i would be writing worse code for years to come and spend more time doing it. I don´t see why it should take a lot of time coding in Java. Because it might be some extra lines to code? I don´t think so. Cut paste is fast ;P ..nah, i think many java comments often state lack of knowledge. Maybe not of the java-syntax allways, but in java thats only half of it. Sure you could design your code close to a PHP script, or use the verbous jdbc api to connect to the database but that is just silly. Who use that directly? Maybe u like the Ruby on Rails db-handaling, well just pick up the java equivalent framework for it, or Hibernate(though i wouldn´t), or spring jdbc. Reusable libraries is what really makes java shine. Spring, Sitemesh, Mule... maybe hard to find the best ones for a novice though. I really love using simple api´s without eliminating flexibility when needed. Most highly configurable, and most are open source anyway. Also fantastic community, IDE editors with code completion, refactoring, debugger, profiler, templates ++
Well know your tools guys and use the right tool for the job, so you can focus on what really matter.
56 Comments:
However,I prefer C++ even to Java,ok If you are not very careful ,it is very east to get "Null pointer assignent"....
however C++ is more OOP than JAVA.
thanks for this great article.
This post has been removed by a blog administrator.
Thanks for the essay. Nice to see someone take the attitude of "This will get me flamed, but here's what I honestly think."
My question is, what speed difference did you see between your Java and C++ implementations? People always say Java is slower, and I know it used to be. But while optimizing a math-heavy Java program recently I tried rewriting it in C and was surprised to see only about a 20% gain. Aside from the lag when starting up a Java program, what performance difference have you found between it and C++ or C? There are many conflicting benchmark results out there but one often smells a bias.
I'm trying to choose between Ruby and Python myself for quite some time now. Thank you for this article.
But for me the biggest issue is availability of 3rd party libraries. I would like to hear others' experience on this.
I program mostly in C++, but sometimes I just want to cry when I try to find a C++ library for some specific functionality and I find zillion Java libraries, some of them famous and half of them free, and total of three C/C++ libraries, all of them commercial.
On the topic of speed, I often compare things with my Java friends. My (biased) conclusion is that Java comes near the C++ speed only in brute math tasks or similar. When you try e.g. parsing of large xml files, working with large recordsets, desktop gui showing much data and refreshes constanly etc - with Java you are either dead or nead a $$$ server to run it on.
But I also noticed it might well be because of a human factor: people that program Java, often don't consider performance at all during design, maybe Java unintentionaly encourages that approach (like VB encourages spagetti-coding)?!
lack of multiline comments in Python/Ruby was annoying
Python has had multiline comments for years. Indeed it is a staple of the documentation tools.
"""
This is a
multiline comment
"""
Now perhaps Ruby does not have them. But if so, you should explicitly state that Ruby doe snto have them. Don't tar Python with that brush because of Ruby.
Oh, I am delighted that I'm not the only one that sees the runtime _only_ type checking of python as a problem. I can attest you from experience that it's very prone to runtime breakage in large programs. Unit tests don't help, because they have to be written by a human. Instead of writing unit tests I could as easily (or easier) just add some type names here and there if the language allowed it. This is the bane of python. However, Guido Van Rossum is aware of the problem and there is a discussion underway.
And there is boo, too :) http://boo.codehaus.org/ it's like python but _with_ optional static type checking and type inference.
As for C++ STL, you like it, really?
They always were my biggest critic point in C++.
From a pragmatic standpoint they are as bad as it gets.
No decent string operations, no parser (lexer) classes, "global" functions scattered all over the place instead of more sane member functions (find, copy, anyone?) - and I don't care about if their implementation was easier to write that way. I care about the interface and that is bad.
Aproros interface, no interface types, no Components model (COM/Corba/dbus) and _no way to add it via RTTI either_.
Oh yes, no RTTI.
No decent namespaces (only as an afterthought and not usable).
Hand-Written iterator classes instead of yield / generator pattern. Ever tried std::transform tolower? Needs a cast of the ctype tolower() function although the prototype looks ok and _works_ after casting...
Then one is supposed to do manual memory management but the container classes when used with pointers as items do not free the memory these point to. Trying to use non-pointer item in a container class gives rise to error messages so unreadable that I could understand Klingon better (and I can't understand it at all).
auto_ptr. Need I say more?
=begin
This is how to
multi line comment
for Ruby
Note: No indentation
=end
Great article. Interesting to see I'm not the only one struggling with the Java vs Python vs Ruby question. It's a tough decision.
I agree with your comments on C++. But STL, I really didn't like it. I think these days people really only do use C++ if they have to! :)
It's tempting to stick with Java and forget Ruby/Python, but coding in all the extraneous crap that you have with Java is a bit depressing.
In my evaluations I did a similar exercise to yourself and compared Perl, Python, Java, Ruby, PHP5. I really liked Perl funnily enough. However, like you I didn't reach any real clear decision over Python/Ruby/Java. In pure language terms I probably liked Ruby best. But there are some things I like about Python. Java also has some major strengths, with it's great libraries especially Swing. Very frustrating as I couldn't reach a clear decision about which one to really pump the time into!
I guess ultimately it's the application that will dictate the best language..
You got the speed thing as a usually premature optimization, but missed the point about the testing. its not 'testing for type correctness', its testing for correctness, full stop. In dynamic languages like Python, variables can be associated with more than one type in the life of a program. I know, this can seem weird to a static typing aware programmer, but when you start to use a dynamic language like Python idiomatically, you can take advantage of a very powerful technique called 'Duck typing' (http://en.wikipedia.org/wiki/Duck_typing)
Touching on speed again. Python's conciseness, readability, and interpreter, optimise speed of development and maintenance over languages like C++ and Java. Because you were porting a program between languages, this aspect may not have been revealed.
- Paddy.
P.S. Pythons doctest module allows you to effortlessly take the 'scriblings' you might do in the interpreter whilst creating a class and turn them into unit tests:
http://en.wikipedia.org/wiki/Doctest
Great post.
I personally (and maybe I'm the only one) think Ruby's syntax is awful and hard to read in a lot of ways.
Some of the conventions Python takes on seem to be more effective to me, but I am not reasonably experienced at either. I totally agree about the multi-line comments though.
One thing I would consider is something like Jython (a Java compiler for the Python language). It seems to be a pretty effective way of using Python for productivity and gaining many the benefits of Java.
On the Java vs. C++ performance issue, I have noticed less and less a difference over the years. I wish I had a link, but I have found several reports in the past showing that most of the speed differences that exist now are the result of Java's array bounds checks, a stability / security issue. Just a thought.
Anyway, great post.
I'd love to see Rebol added to the comparison. It's a shame so few people even know it exists...
http://musiclessonz.com/rebol_tutorial.html
Dave, thanks for a great comparison article, and for using a clear proven example,
You've made me seriously consider dropping Python for Ruby. That explicit 'self' is a pain. But other comments mention boo, which may be more useful in the end, with the ability to do type checking.
Optimising for speed? There are only three rules to remember, said my programming guru, Peter Juliff, way back in 1979 (!):
(1) Don't do it.
(2) Don't do it.
(3) Don't do it yet.
C++ comments, in order of importance:
* There is a lot of duplication in the private methods. It really could be factored out (that goes for the other languages too)
* Needs copy constructor and assignment: The pointer members will almost certainly break without proper copy methods defined, or declared private (and not defined)
* The public constructor should probably be declared explicit
* A default constructor would probably be good -- STL classes usually have one
* Put public methods first in a class
* Limit file to 80 chars per line (fit on web pages, etc., better)
* Method implementations inside class declaration mean the compiler will (try to) inline. Is that really wanted? (not if it bulks-up the exe unnecessarily)
* Stroustrup and Meyer suggest "Type* name" rather than "Type *name" since the embellishment is part of the type
* Some method names are not verb-ish
In return I can put a couple of my own dual-language implementations in the firing line:
Octree in C++ and Ruby:
* http://www.hxa7241.org/articles/content/octree-general-cpp_hxa7241_2005.html
* http://www.hxa7241.org/articles/content/octree-general-ruby_hxa7241_2005.html
Minimal renderer in C++ and Ruby:
* http://www.hxa7241.org/minilight/
I found that Ruby seems to come out close to half the size of C++. And that Ruby is 1000 times slower than C++ (!!!).
You should check out Lisp...
I know, I know, it's not as "cool" or as "hip" as the languages you tested, but it would win your little test hands down.
Check out this much more comprehensive comparison between lisp, c++, and java--
http://www.flownet.com/gat/papers/lisp-java.pdf
I quite like the article, its written in a very unbiased way.
I'm not a fan of ruby, its syntax is quite ambiguous in feel, it feels like its so open ended, I could get something wrong easily and never notice. Python doesn't have that approach, it looks clean, and uses the consistant ":" for almost everything. However, I haven't used much Ruby and I'm slightly biased.
Theres allot I could say about C++. Between all of the languages, C++ is the only language that gives the programmer great amounts of flexibility in design while sustaining its speed at runtime. Indeed, C++ feels more complex than the other languages, but I keel that over by just "getting it done". To a noob, C++ is probably not you're friend. To a Pro, C++ can be your best friend, as you gain experience, most of those runtime errors that used to plague you dissapear. C++ also becomes allot easier when you use Boost libraries, which make so many idioms a hell of allot simpler.
I agree with you that c++ should be used when speed is a requirement, it being the fastest of all the languages. I have a need for speed more than others, so I tend to write lots of c++.
However, overall my language of choice is python. Python has the best "standard" library of any language. Everything other than niche libraries are included twith standard python, I can get 99% of what I need to achieve with the standard python library distributed with almost every python implementation. Python is convienent and productive to write in as well.
As for Danny Milosavljevic, His comments are wrong. C++ *has* RTTI, in the form of typeid, and dynamic_cast. As well, C++ has usable, workable namespaces. The standard algorithms are globall functions not because its easier to implement, but because its more intuitive and flexible. Those same algorithms work on pointer types, and home made classes and iterators (I've done this more than once). As well, using auto_ptr in a container is a dumbass idea to anyone who knows c++ well. auto_ptr isn't copiable, and thats a standard requirement for containers. And, the reason that containers holding pointers don't delete what they store is because they can't determine ownership. More than once I would have died if containers deleted their pointers, it would have been symantically incorrect and forced me to take a harder approach.
Great article, thanks again.
You said:
"My general feeling was that Python annoyed me in ways that Ruby didn't, but I think those annoyances would disappear if I was using Python all the time."
Well, I tried using Python a lot, and the annoyances got more annoying, especially if you also are writing code in other languages.
The worst thing about Python is the invisible dedent. Two dedents look like one, depending on your choice of indentation. An indent is always a single indent, no matter the width. Yet, this is one of Python's most touted feature/bug. A Python-aware editor helps, but the same is true for fixed-form Fortran77.
So, if Ruby and Python are about the same, the choice should be on your preference for coding style. Some people like Python's style; I hate it.
It seems rather lame to pick a language based on coding style rather than syntax and functionality. Python would be a clear winner (to me) if it supported an alternative style.
-- Joe Krahn
You said:
"My general feeling was that Python annoyed me in ways that Ruby didn't, but I think those annoyances would disappear if I was using Python all the time."
Well, I tried using Python a lot, and the annoyances got more annoying, especially if you also are writing code in other languages.
The worst thing about Python is the invisible dedent. Two dedents look like one, depending on your choice of indentation. An indent is always a single indent, no matter the width. Yet, this is one of Python's most touted feature/bug. A Python-aware editor helps, but the same is true for fixed-form Fortran77.
So, if Ruby and Python are about the same, the choice should be on your preference for coding style. Some people like Python's style; I hate it.
It seems rather lame to pick a language based on coding style rather than syntax and functionality. Python would be a clear winner (to me) if it supported an alternative style.
Great article, indeed!
I personally like Python from more than three years of using it.
I would like to point out that you can have multi-line comments in Python by using triple quotes """ or '''. Try out the code below
def foo():
# This is a comment
x = 'hello'
'''This is a block
comment,
How do you like that?'''
return x + 'world'
in Python (currently 8th line of code), why not simply use
red,black = 0,1
instead of
red,black = range(2)
Ruby is a clean powerful languige that is slower but more powerful than any other populer languige. ruby has good suport for the functional stile using blocks and iterators
This is certainly not good Ruby style. You should do
class RedBlackTree2 < Struct.new(:val, :left, :right, :color)
So you'll get copy, accessors etc for free.
Another example:
def find(key)
result = nil
if (key == @val) then
result = self
elsif (key < @val) then
result = @left.find(key) unless left.nil?
else
result = @right.find(key) unless right.nil?
end
return result
end
should be:
def find(key)
if key == @val
result = self
else
leaf = (key < @val) ? @left : @right
leaf.find(key) unless leaf.nil?
end
end
And this:
print '(' + n.val().to_s() + ':' + n.color().to_s() + ':' + d.to_s() + '), '
should be:
print "(#{n.val}:#{n.color}:#{d}),"
Interesting post. I'm pretty much a Ruby convert these days, coming via Java from a strict C/assembler background.
I never did like C++. Always seemed like objects bolted onto C. The syntax groans under the weight of all those overloaded keywords - in particular, you seem to be able to slap a "const" just about anywhere in a definition / declaration.
I love Ruby but I appreciate that Python is slightly more mature and able to do pretty much all the same things as Ruby, but I find Python's syntax sickeningly reminiscent of Cobol (all that indentation). Also, really really useful things like generator functions are so much easier in Ruby.
However even Ruby has drawbacks - yes, the error reporting is abysmal, and like you I find aspects of the syntax arbitrarily ill-conceived (my pet hate is the stupid case/when construct - what's wrong with switch/case?!!).
Perhaps the winning language will be just like Ruby but with curly braces instead of begin-end, and all those other funnies standardised?
You mention that dynamic typing is a huge productivity gain. Can you eloborate on that ? Is that because the code is less verbose, or because it alleviates the need for compilation ?
Thanks,
python python python !!!
static typing is a correctness win ...
dynamic typing is a productivity win ... at the cost of some risk
I think that the point is ill-posed: what really matters is the average number of unnoticed errors after testing. With static typing you know a priori that there will be no errors of a certain class: but how can you infer from this that total number of errors will be smaller?
Given the same programmer, there is no doubt that in Java with stronger type checking there will be less errors than in Java with sloppy type checking. However is class and number of coding errors invariant with respect to the programming language adopted?
What one really needs is experimental or psycological evidence that static type checking makes unnoticed coding errors less frequent.
Great essay, thanks.
I am an experimenter of languages in Bioinformatics domain.
My Rating of programming languages
in Bioinformatics domain is :
Java > Perl ~ PHP > C/C++ >Python.
Microsoft languages are out of race. (As u know platform issues)
I think a big conspiracy is happening to null Java because all the famous writers of Java are now moving to Python/Ruby. May be they are lured by bigger corporations which use Python along with their propreitory languages.
But as you will see soon in the coming years, Solaris OS will dominate and Java packages for task optimization will capture market.
Let me tell u simple reasons why Java's best:
1) python and ruby can't handle mouse events for complex graphical applications that load on a web page. ( Meaning u can't drag a cubic spline on a web page and at the same time change values)
PHP(Applet) and Perl (For windows due to Tk plugin) can achieve this partially.
2)In PHP you can never tell how many bytes of a file have been transferred to the server when you try to make file uploads.
3) In Perl you can do everything but writing secure web apps and support for OPENGL is not easy. Writing molecular modeling tools requires good supporting libraries.
Also server side image mouse events is yet to be achieved with relevant plug-in that works for all browsers like Java.
4) Python is wonderful for standalone applications but web application development can be nightmare for new users. Using Pyrex also doesn't improve speed.
5) Ruby is no good when it comes to graphics. Also to add AJAX, JSON are not the only things that are highly important in web apps.
6) Finally looks like programmers may want C++ Server pages with no pointers. (Security)
7) I agree that opinions & choices vary from one domain to other but remember Bioinformatics is the place where you tend to stretch the capabilities of languages most due to complexity of problems.
Just a comment on why Ruby uses "begin/rescue/ensure" and not "try/catch/throw". Ruby has "catch/throw" in the language but for a different purpose, to escape nested loops much in the way you would use flags and break statements for (or named loops) in other languages. For example rather than:
flag = 0
while(true)
{
while(true)
{
if(a) { flag = 1; }
if(flag) break;
}
if(flag) break;
}
You could do:
catch :flag do
loop do
loop do
if a then throw :flag end
end
end
end
Just thought you might be interested in that tidbit as I just found this out.
I'm currently using Ruby for a mostly academic project because I like its flexibility/syntax more than Python but I think if I were going with a bigger more production project I'd use Python because it has a larger community/more readily accessible and stable modules.
Thankyou very much for this nice over view of four languages. I really found Python/Ruby part very interesting, as I have been to jump on this band-wangon too after years of Javalisation! So far, I can't make a clear choice about which way to go: Python or Ruby. Although I really like Ruby syntax and OO Completeness but Python seems to have more tools availble for various purposes..
Conclusion: I am going to try both :-)
For Python, you want to use PyLint.
Nicely done.
I would argue that other big steps forward for Java are: A consistent error reporting model and the ease of creation of libraries (C++ focused on ease of use of libraries, but creating them was still hard. We can see the results in far more Java libraries).
In my experience Python is pretty darn fast much of the time.
The fact that Sun is directly supporting JRuby development is very interesting. I could easily see a future where JRuby is the top-level language that makes use of Java components. Rather than writing everything in Java.
Thank you for the essay. What I miss in the comments sofar - or is it so obvious to everybody? - is that it usually boils down to 'the right tool for the right job'.
I realize that the Red/Black tree was used as an example on how code looks, not as a serious implementation, but it's still deeply rooted in the C/C++ domain. Fact is that the Python code was mostly C++ code ported into Python, and not a Pythonic solution for the problem - but then again, why bother with the tree - I'd probably use a dictionary in the first place. I can only assume that the same applies to other languages. And the example fails in that aspect in the pay-off for performance loss of Python/Ruby compared to C++: code that is much, much shorter (and, assuming equal proficiency of the languages, probably much easier to understand)
Type checking? I miss it in Python, because I'm so used to it - but most of my Python scripts are so simple that they don't need type checking. Recently I had to convert around 1000 graphic files from one format into another. The only batch converter that was available could only handle one directory at a time and my files were spread out over 100s of directories. A Python script that renamed them, copied them to a single folder (had them batch processed) and copied & renamed them back was written and executed in less than 30 minutes.
Using C or C++ for a task like that didn't even come up in my mind.
On the other hand (warning: flame alert) scripting my Excel spreadsheets with Python would be overly complicated - it's much easier to use the built-in VBA for that. And as while Python performs excellent in a product as Spambayes, I would still be very distrustfull of the performance of a spreadsheet or database server written entirely in Python - C++ gives much better performance for that kind of software.
And that makes is so hard to compare different languages with each other - inside their domain their hard to beat, outside they're a lame duck.
Oh, and "Bioinformatics is the place where you tend to stretch the capabilities of languages most due to complexity of problems" - I don't buy that as proof that Java would be 'best'. If it were, all supercomputers would be programmed in Java, and they aren't.
Thanks for the comparison.
What about building GUIs? Both Ruby and Python use Tk as their default choice.
One other commenter raised the point that red-black trees are usually used to implement what associative arrays, also called dicts in Python and hashes(?) in Ruby. You then go on to state that Java and C++ are much faster than the dynamic languages.
The dynamic languages, especially python, rely heavily on the speed of their dicts. The code implementing Python dicts is highly optimised.
A different speed test would be to pit red-black tree implementations in java and C++ versus native dicts/hashes in Python and Ruby, to store N trees/dicts/hashes as the items of another tree/dict/hash; where the N subtrees/dicts/hashes contain M different integers.
Set N and M to around 1000 and compare performance.
Look at the code for the implementations.
You would probably find the dynamic solutions to be a few tens of lines of code, and the static anguage examples several hundred lines of code. The Python/Ruby examples would be created in 30 minutes and a doddle to test.
I doubt anyone would want to complete the Java or C++ example as part of a blog post. It would take too long, except if they employed an *external* library.
On the explicit-static typing verses dynamic typing issue, I'd love to have the advantages of type checking without having to add type annotations to my program - inferred typing? But even then, it would need to allow duck-typing.
- Paddy.
One other commenter raised the point that red-black trees are usually used to implement what associative arrays, also called dicts in Python and hashes(?) in Ruby. You then go on to state that Java and C++ are much faster than the dynamic languages.
The dynamic languages, especially python, rely heavily on the speed of their dicts. The code implementing Python dicts is highly optimised.
A different speed test would be to pit red-black tree implementations in java and C++ versus native dicts/hashes in Python and Ruby, to store N trees/dicts/hashes as the items of another tree/dict/hash; where the N subtrees/dicts/hashes contain M different integers.
Set N and M to around 1000 and compare performance.
Look at the code for the implementations.
You would probably find the dynamic solutions to be a few tens of lines of code, and the static anguage examples several hundred lines of code. The Python/Ruby examples would be created in 30 minutes and a doddle to test.
I doubt anyone would want to complete the Java or C++ example as part of a blog post. It would take too long, except if they employed an *external* library.
On the explicit-static typing verses dynamic typing issue, I'd love to have the advantages of type checking without having to add type annotations to my program - inferred typing? But even then, it would need to allow duck-typing.
- Paddy.
Good article. I can tell you know what you are doing because you are using jEdit. :)
I think there is an advantage of Java that is left off in this article. That advantage is that Java libraries can be learned and utilized faster because return types from methods (or functions) are discoverable in the API documentation for a library.
That may seem like a minor point and it would be to someone implementing a low level algorithm like a red-black tree because you didn't use any third party libraries. However, I think the main advantage of java is all of the ways in allows us to reuse libraries written by others. Java in that case can be quite efficient because it allows us to understand and reuse someone's library quickly and that's a major gain in terms of productivity for me.
I think that the ease of library integration is of great concern for a high level language.
I would argue that, since several of the posted code examples are not good representations of the expected style of each language, the assertions about the languages may be invalid.
EG. Suggesting that dynamic typing is a huge productivity win certainly can't be based on lines of code when the languages aren't used appropriately.
EG
Ruby's to_s()
return '[' + @val.to_s() + ',' + @color.to_s() + ']'
Java's toString() as it should be
return '[' + __val.toString() + ',' + __color + ']';
Instead the article uses 3 lines for java. There are others but this just illustrates that revised versions from language experts should be produced and a follow-up written. The assertion are _likely_ to still be valid, but at least they'll also be based on valid data.
NB: I'd also like to see timing data giving us a measure of statements such as "C++ is way faster than java" - I expect it is, despite being in favour of java and being aware that many evangelists will point to other test data as counter-arguments. I'd just like to see the assertions made here backed up with numbers.
Thanks for your very interesting analysis !
I'm a Python coder with a background in C, C++ and Java (which I still use often)
I know I'm quite late ;) but... what about Pascal derivatives ? http://www.freepascal.org for example.
Modern Pascal, in my opinion, could be still useful in some circumstances. It's a bit verbose but for sure fast and maybe a bit less messy than C++.
Or its time is over ?
The Java code should not contain the underscores __x__. It is one of the advantages of Java that you don't have to play this trick to achieve private naming.
Thanks for the article and comparison.
Recently I was determined to pick from Python and Ruby for a project I'm going to work on. I tried with each. This far I'm convinced that Ruby is the way to go.
I haven't been much of a developer until recently. I've started with C a few years ago, but didn't want to move with C++. I never liked Java much. I know it's a great language. And it's mere capabilities have hold me in awe. But the speed was always bothering me (perhaps I used my old computer too much).
The most annoying things about Python was indent based block defining, which I felt uncomfortable to rely on. Knowing that one 'tab' press was enough to create trouble wasn't easy, especially when I'm using 'tab' key extensively on Linux. :) I know I haven't used Python that much, so I tend to be uncomfortable using Python. Learning that Metasploit project chose Ruby over Python was also not helping. :)
Ruby on the other hand seems well designed and cool and easier to learn. And it felt lot better than Java.
Perhaps what I read in an article was true. That Python was a good language which came out in a wrong time, so now it's the time of Ruby.
Really interesting article -- can't find many objective comparisons of these languages.
I'd like to share a few notes, particularly on the C++ implementation:
- I disagree about treating of built-in types and class types being harder in C++. I actually think it's easier in C++, which supports real POD types and therefore doesn't require things like extraneous casts or boxing/unboxing.
- Similarly, there are good ways to generically convert something to a string: either ostringstream (flexible) or boost::lexical_cast (concise). Overloading operator<< first if you've got a custom type.
- I'm not sure what IntNodeVisitor was introduced for, but it's unneccesary. Just fold the visit method back into NodeVisitor. If you did need to customize your implementation based on type (which you don't in your example), template specialization would be the way to go.
- delete 0; is a valid nop in C++ so you don't need to guard against it.
- Most C++ coders use (!a) instead of (a != 0) and similar, and omit {}'s on single line ifs, which would both serve to reduce clutter a bit.
Personally I love strong static typing, it does catch more errors earlier. I wouldn't try to do anything enterprise-class without it.
I absolutely agree about the utility of garbage collectors, first class functions and lambda expressions. They are real productivity boosts. And I'm the first to admit that C++ is a harder language in general.
Thanks again for a great article.
Great post.
I am not going to develop very much my comment but I think C++ and java are a step ahead:
- IDE and tools support.
- libraries. PDF, excel, reports, imaging, net, ws-*, xml, etc.
- java code readiness, imho is quite clear. Scripting languages tend to be tricky soon of you are not ver very carefull.
- static typing. Dynamic is ok if you are a good programmer, but the average might prefer to focus on some more important issues. static also helps you on maintainability as well (distinct developers on the same piece of code).
- Java c++ general purpose. this could not be a strength but i feel java/c++ a more complete platform.
I'ts harder for me to find a productivity gain from python/ruby (on Rails????) on real projects since small ones tend to be quite similar independently of the technology you use.
I prefer java as you could see here but I am not a fan(atic).
Not sure if these points have already been mentioned, but for the Ruby code:
if @right.nil? then return nil end
should be simply
return nil if @right.nil?
For that matter, I've never seen anyone use 'then' after an if statement. You don't need it.
if !l.nil? then
is probably harder to read than:
unless l.nil?
You don't need empty parenthesis on the end of a method call if it has no parameters. You can also leave them off if you have params:
rb_insert_left val, 0
I would change your to_s method from this:
def to_s()
return '[' + @val.to_s() + ',' + @color.to_s() + ']'
end
to this:
def to_s
"[#{@val},#{@color}]"
end
You don't need an explicit return statement. Ruby always returns the result of the last line in a method.
print t
print "\n"
should be just:
puts t
There might be more things that I missed.
I programmed for a decade in C++ and several years in scripting languages.
The thing about the scripting languages is that any library worth a damn is written in C. But there comes the downfall in that the availability of said library on the various platforms is a hit or miss affair. And woe to those that have to write such a library and make it available on most platforms.
Then I got into Java and consuming libraries from a vast reservoir of open source libraries was a breeze. It was a characteristic of Java I noted from day one - it really kicked serious ass over all other languages in terms of libraries available for it. Plus creating the libraries could be done in Java itself - while still being adequate for real world use. Naturally the platform problem was then a non-issue for said Java-based libraries.
Finally I've now come circling back around to scripting languages via a variant of JavaScript, called ActionScript 3. Yes, the programming language of Adobe Flex 2.
So what have they done to JavaScript - which is a functional and a dynamicaly typed language?
Well, in ActionScript 3 they've evolved JavaScript to the point it's very, very close to Java in many respects.
Also, the default mode of the Flex compiler is to enforce strict, static typing, as it's considered the preferred way to program in ActionScript. As added enticement to lure the dynamic script language junkies, they're told that in the Flex Builder IDE the strict typing approach to writing ActionScript will enable them to use this wonderful feature called code completion, which will greatly assist their productivity.
Yes, the irony is several miles deep here.
The dark little secret is that the script language crowd covet the many benefits of static typing - especially as they get immersed in projects of greater complexity and multi-team complexion.
These days I relegate a script language approach to one-off utilities and test code. Or as a means to add programmability to a running application, such as embedding Rhino or Groovy in a Java program.
The industrial strength, production code is still being written in Java, and there's just no serious contender to be a suitable replacement in sight. Yet.
Your article is very well written and very balanced in its arguments.
My thoughts:
On speed, look at this site:
http://www.timestretch.com/FractalBenchmark.html
The author uses a mandelbrot program in various languages as a speed test. Heavy numerical crunching here. you will see that Java is actually very fast compared to Python and Ruby, due to its JIT--Just-in-time compiler. Several dynamically typed languages, including Lua, have JIT projects underway.
Ruby 2.0, coming in 2008, will be at least as fast as Python, based on current benchmarks for the developmental Ruby 1.9, which give Ruby a threefold speed increase. This will help Ruby greatly.
Notice in this test that compiled OCaml, is as fast as C. Objective CAML is a functionally based language, with added imperative workings and object orientation. Notably, it has strong, static typing,but, all types are inferred, so you do not have to type the type names. With OCaml, you can have your cake and eat it too--except that syntactically it is challenging for the non-functional programmer.
I have programmed much java and find it relentlesly verbose. I have used Python and am now exploring Ruby.
I find Ruby to be even more compact than Python, and yet still readable.
Another issue for comparison of dynamically typed lans and Java versus C++ and other compiled langs is the issue of deployment--how to package up an interpreter or JVM with your code so the user does not have to go and install something on their system.There are some solutions for this like py2exe, but it is definitely as issue for non-compiled languages.
This post has been removed by the author.
I made some modifications of C++ version. The modified is almost half of the origin.
Here
The memory leak problem could be solved easily by smart pointer, auto_ptr. Moreover, the structure of RB tree is highly symmetric so that it's possible to merge opLeft() and opRight() into op() staticly by function template.
Well written article. It's helpful given that I'm just learning Python.
Frankly, I prefer Smalltalk - all the nice things you like about Ruby have already been invented a long time ago.
It's too bad no one bothered to popularize this the way that Sun pushed Java.
Dave,
Nice article. I've been programming since 1976. I've gone through all of the simple and standard languages, BASIC, Assembly, hand-coded machine language, C, Pascal and cruised through C++, Java, LISP, Python and Lua. I've looked at Ruby, considered that it was close enough to Python and Lua that I didn't need to learn another one.
For the time-being, I've settled on Python as my main language, dipping down to C as required. Here are the languages that I feel are most comfortable and productive:
Python
C
LISP
I have a few issues with Python. The indentation for blocks was a little strange at first, but I found that it has two advantages. (1) It creates very readable code and (2) Most people don't realize this, but I'm pretty sure the indentation for blocks evolved out of the usefulness of this when you are truly using it in compiled mode. When using a CLI such as IPython or the Python shell itself, it's very natural to use indentation to handle blocks as the CR ends the last semantic block and will likely execute the block of code you just entered. I hope this makes sense.
Having been forced to program in Java again, I've noticed how often I need to go back to the reference manual to get around unnaturalness issues. Things that are simple should be simple. Things that are complex should be doable. You should also be able to keep a basic core idiomatic functionality in your head which translates directly into useful code.
For example, you're debugging and you need to find out why the values that you're getting aren't correct. You toss in a few debugging statements. In python thats 'print'. In C that's 'printf'. In Java that's... System.out.println(some concatenated strings). Ooops. I needed to print an integer. Crap, grab the manual, how do I do that?
Now I know you can use alternate interfaces to achieve the same thing, but again productivity.
Productive programming comes to a stop.
Here's another. Two strings, A and B.
Let's do the simplicity test:
(BASIC ;-)
IF A=B THEN
C:
if (strcmp(A,B)) {
Python:
IF A==B
Java:
if A.equals(B)
Okay, C isn't so natural because its a high-level macro assembler and we can excuse that, but even BASIC gave you a readble string comparison. Python does it nicely. Java bows to correctness instead of productivity.
Java's automagic garbage collection. Nice, but hardly new. LISP had garbage collection 40 years ago.
Here is my bitch about Java. The amount of syntactic and semantic cruft needed to do anything straightforward and the excessive obsession of the Java community in general to wallow in playing OO games to do what anyone else can do in C or Python in less code and much more directly.
In other words, spending 10x the amount of time discussion the intracacies of J2EE, Beans, Spring ad infinitum rather than getting stuff done.
And that's what it comes down to. A tool that helps us get stuff done cleanly, quickly and maintainably without the obsession with the tool itself.
(Don't even get me started with my experiment in sending UDP packets in Java. I had to coerce a buffer through 5 different types before I got what I wanted). Total time to make it work. 3 - 4 days of looking stuff up and going through class documentation. In python I did the same thing in 2 hours from scratch.
Postscript:
In terms of the next great language, I think we should be looking more seriously at D. It's a true compiler, designed by the author of the Zortech compiler which removes the problems of C++ and Java while retaining a clean OO structure and not forcing us into someone's proprietary VM structure.
In other words a true systems OO language that is powerful, compiled and doesn't straight-jacket us. Hop on board the D train.
Have a nice day!
8-)
I had to choose Python over Ruby because of i18n and l10n. Otherwise, I find Ruby more pleasing to code. Moreover Python beats Java, C++, and Ruby in i18n and l10n.
It would be interesting to include Microsoft's C#. My experience has been that C# is much like Java in terms of developer productivity and runs as fast as C++ code.
I feel like some of the issues here are a bit mixed up. I saw execution speed, syntax, garbage collection, OO consistency, type system, and the killer "productivity".
I'll rule out execution speed and productivity from my post because:
-> Execution speed is orthogonal to all other issues: overall, a languages isn't fast or slow. It's available implementations are. As an example, DrGB noted that compiled Ocaml is about as fast as C. But the bytecode is way slower.
-> Productivity is a consequence of the rest (except execution speed). The more, the better. Now, the real question is: how language design influences productivity?
Let's start by syntax. At first sight, the quality of the syntax can only influence productivity by a constant factor. It is largely a question of taste, habits, whatever. A notable exception is customizable syntaxes, introduced by Lisp. With these, one can set up a domain specific syntax, and shorten the program with that. We have here our first Holy War: rich syntax vs (almost) no syntax. A rich syntax is readily more readable, but not easily customizable. This is (very) roughly the difference between having "foreach" provided by Sun, or building it yourself.
Garbage collection. Well, it looks like everyone here agree that a garbage collector reduces burden, and increases safety. Both effects increase productivity. I will add that performance is roughly unaffected by it (contrived examples aside).
OO consistency. I don't know much about OO, so take the following with a grain of salt. I just feel that if each value in a program is an object, whose class inherits from some "root" class, life is better: genericity comes for free, and polymorphism can be used more pervasively.
The type system. This is our second Holy War. Basically, we have four of them:
-> none at all: C
-> Static, manifestly typed : Java, C++ (to some extent)
-> Hindley-Milner. (ML derivatives, Haskell...)
-> Dynamic type systems (Python, Ruby, Lisp...)
The problem I see here is that many posts here sound like: "Ruby is more productive than Java, so a dynamic type system is likely to be more productive than a static type system". I disagree with that reasoning: First, Java and Ruby are too different to draw this kind of conclusion. Second, we have more than one static type system at our disposal. See here a (angry) post which illustrate my point.
The trade-of is easily stated: a static type system doesn't let us built collections of objects of different types, and a dynamic type system catches type errors at run-time rather than at compile time. Consequence: a static type system requires more workarounds, and a dynamic type system requires more tests. I think the way this affects productivity is far from obvious. (Well, I have two exceptions at hand: throwaway code, and "Earth-is-doomed-if-I-fail" code)
By the way, good post. :-)
We are conducting a similar study based on the popularity of Python vs Ruby, Perl, and Python. You can see what we found out at http://www.odinjobs.com/blogs/page/careers
So my question is, how maintainable are these languages for large scale production environments? Which ones are better for operational efficiency? How does Lisp compare?
What scales out, up better?
I made some kind of comparison.
I have implemented the "payroll" application from "Agile Software Development" in ruby. It took me 10 times less LOC than the author wrote it. Great isn' it.
And about maintainability:
I started the whole in oktober. I stopped developing it for a 2.5 month. This week I continued developing and getting into the code was without any headache.
Here is my post about it:
http://orbanbotond.blogspot.com/2008/01/ruby-on-rails-productivity.html
Thanks for a good essay!
I´ve read through all the comments here as well too get a "feel".
I must admit i´ve been a little curious about Ruby & co after all the buzz lately.
I coded a little C way back, but got bitten by the Java bug maybe 8 years ago. Last year i been working with .NET/C# and ajax. (Witch is also nice I think. It´s very much like java but without the community, the high quality open source libraries and also the platform dependent thing of course. Although very nice debugger, ok for GUI coding, and good integration with the (win-)OS)
I think all languages mentioned have their shining areas. C/C++ is a must for low level coding. (started with hardware integration , circuits design and robotics lately, so will bee doing a lot more of that now)
In my opinion PHP, Ruby and Python is very well suited for getting smaller applications or protypes up and running. (Maybe ASP.NET comes in here as well)
Dynamic vs. Statically typed languages thats the question, you say?
Well i mainly create enterprise applications so i better be dame sure it´s up and running 24/7 with the minimum amount of errors and preforms well. Do i dare user dynamic typed, not so sure. It´s like using AJAX in highly critical applications. Goes well MOST of the time.. :-S
(i use it a lot, but not for highly critical areas. Ever seen a 100% bullet proof javascript (witch is client side dynamicly typed by the way;) )
...I think the most important, i my eyes, is to remember the language is just a tool! Know your tools well so you can focus on what really matters. The business logic, and/or algorithms.
I don´t code 10000 lines of code a day. I spend a lot of time thinking , planning and discussing business processes too. I spend a lot more time coding in C# then I would have in Java because i know Java better. But I understands the concepts and get there after little extra effort. What sometimes really take time is find the errors that only reveal themself in the production environment etc.
Personally i think it would take many years coding eg. Phyton to get at the skill level I´m now in Java. So i would be writing worse code for years to come and spend more time doing it.
I don´t see why it should take a lot of time coding in Java. Because it might be some extra lines to code? I don´t think so. Cut paste is fast ;P ..nah, i think many java comments often state lack of knowledge. Maybe not of the java-syntax allways, but in java thats only half of it. Sure you could design your code close to a PHP script, or use the verbous jdbc api to connect to the database but that is just silly. Who use that directly? Maybe u like the Ruby on Rails db-handaling, well just pick up the java equivalent framework for it, or Hibernate(though i wouldn´t), or spring jdbc. Reusable libraries is what really makes java shine. Spring, Sitemesh, Mule... maybe hard to find the best ones for a novice though. I really love using simple api´s without eliminating flexibility when needed. Most highly configurable, and most are open source anyway. Also fantastic community, IDE editors with code completion, refactoring, debugger, profiler, templates ++
Well know your tools guys and use the right tool for the job, so you can focus on what really matter.
daveh +1 :)
Post a Comment
<< Home