The best kittens, technology, and video games blog in the world.

Saturday, February 10, 2007

The right to criticize programming languages

Ling yawning by _Xti_ from flickr (CC-NC)
There are words that I've heard many years ago, which really affected my thinking about discussions and criticism. I cannot recall them exactly, but they went something along the lines of:

You have no right to criticize a programming language, unless you are able to point three things in which it excels compared to your favourite language.

I feel they're pretty deep. For one, if something really sucks so much that you can't name anything good in it, why are you even wasting time talking about it ? Or maybe it has a few good points, and learning them is a better use of time than ignorant ranting ?

It's no secret that I hate every single programming language ever created, and probably most of the ones to come. Right now the one which I hate least is Ruby, and that by no means should imply that given chance I wouldn't change half of it.

Anyway, with this post I want to prove to myself that I can criticize every single programming language out there.

Python


The first language to get the praise is Python. It is 80% Ruby, and even though I miss the other 20%, I'd take Python over pretty much everything.

The first thing where Python is far better than Ruby is whitespace sensitivity. Getting rid of ends and }s makes the code a pleasure to look at, and saves lines that would get wasted otherwise. Higher code density, and more readability. Python syntax is overall cleaner. Now I don't really fancy the way whitespace sensitivity is implemented, as they had to get rid of blocks for it, but the idea is brilliant, and I'd love to see other languages use it.

Python's second win is PyGame. PyGame was the reason I even learned Python, and it's a pleasure to use it. I even tried to get Google fund Ruby version of it in the Summer of Code ?

Python's third win is simplicity. Most of the complex things about Ruby - syntactic, semantic, or whatever - are exceedingly important. Still, Python by being much simpler would be far better language for teaching peolpe to code. Sure, I know all the arguments for using Scheme or Java for it, and by legal overlook starting with C or C++ isn't in the Criminal Code yet, but if you love kids, you surely agree that Python is simply The Right First Language.

Perl


Now it's Perl's time for the praises. Perl is awesome. Without doubt it is historically at least as important as Smalltalk, Fortran, and the original Lisp. The very idea that language should try to be friendly to the programmer, and flexible enough to accommodate to various ways of thinking, was far ahead of its time. Even in 2007, twenty years after Perl's first release, most languages would rather enforce one true worldview. Some people are willing to accept languages' worldview and become Java code monkeys, or incurable C old-timers. Others value their freedom of thought and choose Perl (or nowadays, Ruby).

History aside, Perl still excels in many ways. For one it is pretty much the only language which got Unicode right. Ruby pretends the problem doesn't exist, Python tried it and screwed it, everything else is useless for text processing. Perl regexp engine is still far better than what most other languages have. I do use the features marked experimental, a lot. If you do i18n, defining your own Unicode character classes in regexps is useful more often than you think.

The second thing is LWP. Ruby's net/http isn't anywhere near it, and will never be. Of course, nobody uses net/http for Ruby. They connect to an actual browser with watir or firewatir, or run system "wget", ....

You probably guesed what the third thing is going to be. That's of course CPAN. Ruby with RubyGems is getting there, but it's going to be a very long way. Oh, and I think RubyGems, not Ruby on Rails, is the main reason of Ruby's surge in popularity in the last few years.

Java


Java - the most trendy language to flame these days. It's also the most popular language these days, and these two things seem to correlate. I'm not even going to repeat the list of sucking points now, just go to any other programming blog.

So the cool things about Java. How can I not say portability ? There was never a language as portable as Java. I can take any Java program, put it on any machine, from a mobile phone up, and it will Just Work. Ever tried that with C ? Good luck getting configure not to segfault on you. Even with semi-portable languages like Ruby and Python, you'd still have to tweak it a lot if it uses some non-standard library (as most programs do), is more than six months old, or (heavens forbid), you're trying to run it under a non-Unix box.

The second reason why I'm grateful to people who created Java, is saving the world from C++. C++ is crime against humanity, and its creator is the programming equivalent of Saddam Hussein. Java managed to get rid of C++ without destroying a small country, how not to be thankful for that ? Java managed to get the mainstream a few steps in direction of Smalltalk, Lisp, and sanity. If you look at all currently available languages, it is pretty clear none would be even close. It had to be free from vendor lock-in, actually portable (in practice, not just theory), perform reasonably well, and have familiar syntax and semantics. It's a short list, but in 2007 Java is still the only language on it.

And JVM. It's mind-boggling what people do with JVM bytecode. Sure, every other language has a virtual machine, but JVM is actually portable, supports plenty of languages, is fast, and there are tons of utilities doing cool things with JVM bytecode. Just take a look at AspectJ.

JavaScript


JavaScript is another language I kinda like, even if getting it to work consistently across browsers isn't fun, and the development tools aren't exactly what people learned to expect nowadays.

The greatest thing about JavaScript - it enabled the Web 2.0 revolution. JavaScript is pretty much the only practical way of creating cool portable GUI apps. People tried using Java and Flash and other languages for it, but for some reason it just doesn't work anywhere as well.

That's related thing, but XUL is just wonderful. Firefox plugins are the second way of creating cool portable GUI apps, and they're also JavaScript-based. Do you even realize how much work would it take to create something even as simple as a GMail notifier in anything other than JavaScript ?

Everyone loves JavaScript because it's so important for the Web, but it's also a pretty cool language on its own. It uses very elegant object-oriented system based on prototypes. Ruby singleton classes and some evilness can get halfway there, but no further

PHP


It feels like a faux pas to say there are things I like in PHP. I certainly don't like its SQL injection friendliness, and main namespace with 5121 (and counting) inconsistently named functions.

Still, there are a few cool things about it, like arrays ! Perl introduced arrays and hashes as separate data types, and every single language followed. Perl had little choice, as only context determines whether "1" and "01" are the same thing or not. In languages that don't follow Perl's braindead string-number unification, there's really little reason for keeping arrays and hashes conceptually separate. They're both just keyed containers, so why do we need two ?

PHP applications are very easy to deploy compared to Ruby on Rails, Java, Perl or any other web apps. It's partially because of PHP's ubiquity, and good integration with standard webservers and databases. Of course I'm assuming admin didn't tweak with global language rules (like register_globals).

PHP is very scalable. It is actually used in massively popular web applications like Wikipedia. Ruby on Rails isn't there yet.

Haskell


I don't like Haskell. It's a bondage and discipline language - either you think the way it thinks, or it will make your live a living hell.

The best part of Haskell is syntax. It got whitespace sensitivity right, so unlike Python it still has full power blocks. Laziness and pattern matching simplify programs quite a bit, so they often look like specifications, not like code.

Haskell is also actually extremely expressive. Just take a look at "Functional Specification of JPEG Decompression and an Implementation for Free" paper. Ruby does quite well too, especially with a good library like ActiveRecord, but I don't think it's that good.

Software Transactional Memory. I'm really more into concurrency based on message passing, but STM is cool.

Scheme


Macros. Do I really have to say more ? Macros are great. This point also includes simple syntax tree, and no - CL does not have a simple syntax tree if every code walker needs to understand (loop ...). Ever tried working with Ruby's ParseTree ? It does work, but it's really ugly.

It is just unbelievably semantically elegant. I don't know any other language with this level of power and such elegance and simplicity. It makes even Python looks complex and ugly (with bolted-on object-orientation it's hard not to look ugly, but anyway). Other Lisps are usually really horrible here.

Symbolic computations in Scheme are very easy. Just a single main data structure (linked list with symbols), macros, simple pattern matching, tail-call optimization (it makes many things simpler), etc. Ruby surely beats languages like Java here, but is far behind Scheme.

Erlang


Erlang seems pretty cool. Just look at Erlang: The movie at Google Video.

The absolutely coolest thing about it is builtin support for reloading code without losing state. I routinely code half-way solutions for this problem in Ruby, Perl, Python, or whatever language I'm using. In many cases it speeds up development by a factor of ten.

It can also do massively distributed computing based on message passing. Ruby barely does multithreading, and relies on RDBMS-based solutions for scalability.

If you expect Smalltalk/Ruby-style "everything is an object", Erlang is disappointing. But if "objects" are redefined to mean "lightweight processes", Erlang starts to make sense. I'm not really convinced "one object per process with strict message passing" model is better than Smalltalk/Ruby model, but I'd like to experiment with it a bit some day.

Smalltalk


Smalltalk program is a living being, not a dead object. I keep trying to make my programs a bit less dead, and Smalltalk is at the end of the road. Either that, or Erlang.

Smalltalk is object-oriented without any compromises or complications. The only operation is sending a message. Ruby makes a lot of compromises to feel more familiar. The compromises made it less flexible, more complex, less reflective, and also much slower. Do you know how exactly String#=== sets $1 ? Can your class do so to ? (It can, but the method must be coded in C, not Ruby). Can you take object's method, unbind it, rebind, and call ? (Try it on a cloned singleton) What are semantics of protected visibility ? Why so many kinds of class variables ? The complexity means it's much harder to metaprogram without accidentally breaking something in process.

Smalltalk is based on images, not on a bunch of text files. Text files are cool, but needing a few irb sessions, and cut and pasting code between irb and text editor is seriously annoying. And to think that some people have to manually compile programs and don't use svn.

C


The coolest thing about C is Unix. C makes Unix possible. If you don't know why Unix is so cool, just put aside anything you're doing right now, take a couple weeks' break, and learn it well. You're going to thank me later.

C is very pretty language for low-level memory manipulation. Providing only low-level memory access is of course one of its worst weaknesses, but at least they got it right. With C it's just so easy to create fancy data structures, and use every last bit of them. Other languages usually go the other way and provide only high-level memory access. For 99% of programs, it's a better choice. For the rest, we have C. A related issue is fairly simple semantics (at least without aggressive optimizations or multithreading, then it gets nasty). It lets you experiment with many things that are simply not possible in other languages. And few other languages have decent inline assembly support.

C can access a really huge number of libraries. It takes a lot of work to get them work well together (every non-trivial C library of them defines own string type, own pseudo-oo system, many even include own memory manager), they're not portable, they're not secure, and they tend to segfault at random, but the sheer number of available libraries is about as high as Perl's.

C++


C++ is easily the worst language ever. It's one thing to say good things about a language when language in question is Python, it's a completely different thing when it's C++. What next ? Praising Bush's handling of Iraq ? Still, I think I can say something good about it.

It can be used as better C. Low-level, fast (with template hackery easily faster than plain C), backwards compatible, and still significantly better. Few people use C++ that way. More often than not they create monstrous APIs and programs that break under weight of C++'s semantic complexity. But C++ has potential of being "better C".

Template metahackery is fun. Most of the time it's totally useless, and plain C would more than suffice, but who wouldn't want a new programming toy ?

C++ still seems like the only way of creating fast low-level data structures and algorithms with half-decent, and zero-overhead interfaces. C is just too ugly for that (you cannot even have a decent complex_t in C), and everything else adds a pretty high overhead.

Summary


I said a lot of good things about many languages, and I hate them all anyway. I tried to keep true to my feelings, and avoid simply repeating the party line why something is cool. I could write about Objective Caml, Prolog, C#, CL, and all other languages, but I wanted to keep it reasonably short. Maybe one day I'll write another part.

If you want to join the fun, go ahead and write some really cool things about languages you hate most in the comments. I'm not going to delete anything, even if you praise COBOL :-)

Translations

Alyona Lompar translated this post to Ukrainian.

Maria Ramos from Webhostinghub.com translated this post to Spanish.

65 comments:

Joshua Haberman said...

Comparing Ruby's net/http to Perl's LWP is comparing apples to oranges. net/http just implements the HTTP protocol -- LWP layers a user agent on top of that. If you want something like that for Ruby, check out WWW::Mechanize, which is pretty awesome.

taw said...

My bad, I got so used to Perl stdlib that it was simply beyond my imagination that something as basic as GETting a plain http(s) URL would need installing another library.

WWW::Mechanize seems to be more or less what I need. Any chance of it becoming part of the Ruby stdlib ?

Anonymous said...

file = open('thefile')

require 'open-uri'

google = open('http://google.com')

Anonymous said...

Funny. I switched away from Python because I thought the white space thing was messier. Also, I hated the self. disease within the classes.

Alan Little said...

> I'm not going to delete anything, even if you praise COBOL

There's a challenge you may not see many people rising to, but I'll give it a go. From my (thankfully) brief and far from expert COBOL programming career long, long ago, I recall rather liking the way you could use REDEFINE to give you multiple different views of a single data structure.

taw said...

Anonymous: open-uri (like net/http) doesn't even get Basic authentication. It simply ignores username/password if you ask for http://username:password@some.host/path. Most web services require that, so this makes it pretty much useless to me (LWP works just fine).

Anonymous: Oh yeah, self. disease is one of the ugliest things about Python. White space is a personal issue of course - I really like it.

Alan Little: I'm impressed that someone had guts to praise COBOL ;-) But it must had done something right, it used to be pretty popular, and you don't become popular without at least some technical merit.

Anonymous said...

OK, C++ is hideously complex, but there are a couple of very nice things I can say about it.

First, it doesn't treat me like a child. Yes I know multiple inheritance and operator overloading can be abused. So can alcohol, but I still want a Guinness every once in a while.

I'm also quite a fan of C++-style generic programming. Of course, it comes with the monstrosity that is C++ template syntax, but at least conceptually, that style of development seems more "right" to me than the classical big OO hierarchies.

Possible Piper said...

Good luck with the taking any Java program and running it on a mobile phone thing.

Maybe in an alternate universe...

I think your criticisms of C++ are overly harsh. As an earlier anonymous commenter implied, C++ is a very powerful language which is easily misusable. That doesn't mean it's intrinsically horrible though - it just means people need to learn to use it right.

Unfortunately most people don't - but then again, that applies to a lot of languages with the possible exception of ones like Haskell which shove their worldview down your throat and make you swallow by simple expident of not allowing you to consider it any other way (okay okay, that's assuming people don't find out about MVars).

As to why Java doesn't work out for portable GUI apps? Try that Swing and AWT both suck. The Java bindings for GTK+ look pretty nice though, and they'll work on most major things. Shame it doesn't have operator overloading though.

Anonymous said...

The right to criticize programming languages? Or the right to compare programming languages to your current favorite? I hate Ruby and I hope it fails miserably. Not because of the language itself but because of the community of fanboys and the hype machine. Go program something G**DAMMIT and stop writing about how great Ruby is('nt)!

Anonymous said...

COBOL was one of the few languages of its time with decimal numeric types and numeric formatting built-in.

I've heard it also got preferential support and marketing from the vendors (more resources went into the COBOL compilers than the others).

Daniel Yokomizo said...

Let me see: Cobol has redefines which together with its data specification format make it perfect for dealing with column delimited files, it has a pretty decent primitive decimal arithmetic support, move corresponding is nice and there's builtin support for a decent "order by" declaration (instead of the mess that is java.lang.Comparable). Also it has primitive AOP declarations.

Weapon Liu said...

I think you should get to know something first before you can judge it.

> Template metahackery is fun.
> Most of the time it's totally
> useless, and plain C would more
> than suffice, but who wouldn't
> want a new programming toy ?


How often do you use template in C++, how many C++ libraries that's based on GP have you ever used? Even this: How much of the syntax of C++ template do you know?

C++ GP is by far one of the most powerful tools for library construction I've ever seen. And it's not just that I said this, it's a proven fact. It's not "just some language toy that's fun to play with", it's a real-world industry strength technique. Look at ACE, WTL, and the whole bunch of libraries in Boost, just to name a few. See how template techniques improve the user interface of the libraries while keeping the performance at their best. See how template techniques is used in active libraries such as Blitz++, Boost.uBlas. See how template techniques support great code reusage, and lose-coupling. Even this: See how Java and C# embraces generics?

Always get to know sth first before judging it.

Sure, templates, when used inappropriately, could be harmful. It could even cause much much worse things that a guy can image. But all the good things of something should be talked based on the case where it's used properly. Even tooth brush could be misused.

Anonymous said...

Comparing Ruby's net/http to Perl's LWP is comparing apples to oranges. net/http just implements the HTTP protocol -- LWP layers a user agent on top of that. If you want something like that for Ruby, check out WWW::Mechanize, which is pretty awesome.

It's a fair comparison, as WWW::Mechanize was originally designed for perl on top of LWP, and only later ported to Python and Ruby.

Anonymous said...

Even this: See how Java and C# embraces generics?

Yes, and that's one of the primary reasons I dislike them and C++. The problem of generics is easy to solve cleanly, as ML demonstrated before C++ templates were invented. Stroustrop even cites ML's abilities as an inspiration, though ML's solution is so simple as to require the programmer to do nothing, while Stroustrop introduced a Turing-complete compile-time metalanguage.

Templates and Java generics are kludge to the ugly Algol-style type systems that C++ and Java have, but the best solutions aren't in building ever-more baroque structures on top of the shaky foundations of ancient languages. The best solutions are found in applying some of the last 50 years of development of type theory like Hindley-Milner type inferencing (as well as newer inferencing algorithms), like Clean, Haskell, Ocaml, and SML do (as well as newer languages for both the JVM and CLR.)

Menno Holscher said...

There were 3 advantages required for COBOL. Mine are:

The record structuring with level numbers. Combined with some judicious use of white space it oraganizes your data beautifully.

The 2nd one has already been mentioned: redefines. You can redefine any data item in a predicate. No coding, just say it and you can use it.

The third is the EVALUATE keyword. When you first see or use it, it seems akward, but when you have written a few, you wonder why more modern languages (e.g. Java) do not have something similarly elegant.

Evan Driscoll said...

I'm going to add my voice to those saying you're too harsh on C++. For starting off by saying that you shouldn't criticize a language unless you can think of three ways in which it excels, your analysis of C++ is pretty darn poor.

I have recently put my finger I think on the biggest reason that I really like c++. More than any other language I know with the very notable exception of LISP/Scheme, between templates and cpp macros C++ gives you the tools to almost invent syntax.

Look at Boost::Lambda. It provides a somewhat limited form of lambda expressions for C++. Show me ANY OTHER LANGUAGE that doesn't give you lambda expressions as a feature of the language, but gives you enough power to create it.

C doesn't have strong typedefs, hence neither does C++. (In other words, if you typedef int myint, ints and myints can be implicitly converted back and forth. This can be both good and bad.) But you can hack together a macro like STRONG_TYPEDEF(int, myint) that will give you strong typedefs.

Second, counter-intuitively C++ has actually decent support for resource management. Most of your other languages have garbage collection, which suffices for memory management, and most have either implicit or explicit support for concurrency (e.g. Java's synchronized keyword). This takes care of two common resources, but there are a lot more: database connections, files, lock files (e.g. Firefox's .parentlock), etc. You can expand the definition of resources to include anything where you do some action (e.g. allocate memory, open a file), some work with it, then undo the action (free, close). But now we have a lot of other "resources" -- temporary variable changes, setting the mouse cursor to an hourglass during a long computation, etc. Managing these sorts of resources C++ excels because it's RAII idiom and destructors allow the compiler to do all the hard work for you.

Weapon Liu said...

Templates and Java generics are kludge to the ugly Algol-style type systems that C++ and Java have, ...

I would consider C# and Java generics shabby, although they do serves well in their own world. But C++ templates is a well-thought feature. That it's created such a enormous success is the first clue.

Granted, the syntax of C++ template is maybe a little complex and bizarre compared to that of ML or LISP, but hey, C++ is a static typed language, which is an essential constraint when C++ templates was invented.

I found it very interesting that almost every time I see people makes judgment on C++ templates, they focus on syntax exclusively. I mean, syntax does matter, but it doesn't when the powerfulness is much much more important a consideration.

That being said, the complex syntax of C++ templates does come for some reason. Take the "awkward" "typename" for example, it actually was introduced for several reason, one of which is that C++ templates supports not only type parameters, but also non-type ones, which called for a way to discriminate them.

And don't ever forget the fact that once you get familiar with a kind of syntax, it becomes natural to you.

Speaking of the powerfulness, C++ templates is the most powerful generic system in the static typed world. Dynamic languages is totally a different matter in this regard, so comparing C++ generics to that of some kind of dynamic languages is always unfair; they have different aims.

To Evan Driscoll:
Although I'm a big fan of C++ as you're, but, using boost::lambda and strong typedef IS actually not that much of a convincing one.
boost::lambda actually exposes one of C++'s weakness. So does strong typedef. That's why there're a few C++0x proposals out there aiming to solve them by adding first-class language support.
That C++ gives the power to mimic some kind of lambda or strong typedef doesn't mean that C++ is superior in this regard, given that the mimic is inferior.
That said, using boost::function/boost::asio/boost::program_options/boost::smart_ptrs, etc may actually make much much more sense, because they show that how templates can make a component elegent.

Besides, supporting of the so-called active library is one of C++'s special powers that other languages don't have. Blitz++ is a good example. C++ templates makes libraries be able to adapt itself to different user scenarios based on type information supplied by the client code, which, I think, shows another, yet often neglected, powerful aspect of type system.

Evan Driscoll said...
This comment has been removed by the author.
Evan Driscoll said...

I posted a response a minute ago, but deleted it because it was way too long and not on-topic enough I thought.

Granted, the syntax of C++ template is maybe a little complex and bizarre compared to that of ML or LISP, but hey, C++ is a static typed language, which is an essential constraint when C++ templates was invented.

It's also worthwhile to keep in mind that while templates have allowed all the metaprogramming stuff they have, they were designed to fill the role that C#/Java generics do: to make it easy to create containers and such. The fact that they turned out to be Turing complete and useful well beyond this was an accident, and thus the syntax is very unwieldy for doing anything too complex.

That being said, the complex syntax of C++ templates does come for some reason. Take the "awkward" "typename" for example, it actually was introduced for several reason, one of which is that C++ templates supports not only type parameters, but also non-type ones, which called for a way to discriminate them.

That said, even if you accept that C++ has to have typename, I think that it's handled absolutely horribly in the standard. This is what the bulk of my previous post was about; you can read what I said here.

Although I'm a big fan of C++ as you're, but, using boost::lambda and strong typedef IS actually not that much of a convincing one.
boost::lambda actually exposes one of C++'s weakness. So does strong typedef. That's why there're a few C++0x proposals out there aiming to solve them by adding first-class language support.
That C++ gives the power to mimic some kind of lambda or strong typedef doesn't mean that C++ is superior in this regard, given that the mimic is inferior.


But are you ever going to get every language feature that you might want? No way.

But in C++, that's okay; because you can fairly often make the language work for you.

Anonymous said...

Speaking of the powerfulness, C++ templates is the most powerful generic system in the static typed world.

SML (Ocaml), Haskell and Clean are static typed too.

Jason Murray said...

After 10 years as a nuclear plant mechanic, now as a neophyte programmer, I have to say there is one rule that applies to both worlds. "Always use the right tool for the job at hand." I use PHP for web work, PERL for quick and dirty scripts to get something done on a UNIX box, Visual Basic or C# to crank out a quick and dirty utility on Windows and C++ when I need low level tools. I don't consider myself a master of any of them, but I can use each when I need to. It's knowing when that can be the challenge.

Anonymous said...

Just like some other guy said, i hated ruby. Mostly because the community is full of `designers' who have no idea what programming is all about, and hype the language as it was the Holy Graal of programming. Now, i hate the hype, but like the language. Not the most powerfull one, but a usable one (which is saying a lot, given how most languages simply suck).

When i was a young happy newbie (not so long ago) i liked C++. After 5 months with it, it felt simply hideous and unecessary. I cant say i like OO because C++ just made it so ugly and obstrusive i couldnt think straight. But I'm sure some sessions of Smalltalk will cure that.

C beats evey language, except Scheme (Scheme here representing the whole LISP family, because there was no standard Lisp until Common Lisp), mostly because of UNIX, but because it is a really great language. It allows you flexibility and freedom, even if that may kill the average BASIC-infected Java-maimed programmer. And it is the main reason why almost every common language has a similar syntax (the C-style syntax). Thats how important it is.

Java has no portability. Thats a lie. How many plataforms has the JVM been ported to? Now compare that to the number of C compilers for different architechtures. Buggy and segfault code is better than no code at all.

Scheme is easily the best language in that list (syntax, semantics, power, beauty, flexibility). Lisp could be there too. And even if they are underrated (considering the LISP family is without a doubt the best set of languages ever invented), i dont expect people to understand that, mostly because anyone calls themselves programmers nowadays, and if you make cute windows with swing and sparkling web stuff with rails it gives you an illusion that you might know anything about computer science.

Perl's syntax is an abomination as much as C++'s. Historically it may(gasp!) be considered highly important, but the language itself is not a thing to praise.

thats my 2 cents, and it is not anything the original post had in mind (since its not criticizing, mostly flaming with a point). but anyways...

Robert said...

Tcl beats the pants off every other "dynamic" language in terms of Unicode. Tcl has had it right for a long long time.

Anonymous said...

I just wanted to say thanks for two things:

- JRPG (discovered through Wikipedia a while ago and now I am using it along with podcasts to start teaching myself Japanese)

- this post (found by accident after coming here through JRPG but very interesting as I have been looking at Python for a while with a view to teaching myself to code and it is useful to see the good points of various languages set out so succinctly)

Good job Tomasz!

Anonymous said...

Taw. you just said all that so that you are now free to criticize these languages as much as you want to, not? :P

On the other side it is interesting to see that each language has its own specialties, guess they each focused greatly on their special features.

taw said...

I'd like to thank everyone for the comments, including people who praised C++ and COBOL.

Anonymous: It seems I need to do a bit more research before I can criticize whatever I want. I thought I can say something good about every language out there, and then FreePascal-coding friend of mine found this post. Fortunately he seems pretty much converted to Ruby nowadays.

Janne said...

Fortran IV. First of all, it has a very nice three way conditional statement usable for everything:

IF(exp) Line1, Line2, Line3

If exp<0, go to Line1; exp=0 go to Line2, and exp>0, Go to Line3. Easy as cake.

Second, there is no (and I mean no) limit as to how you can use the EQUIVALENCE and COMMON statements for, well, anything, without having a bunch of pesky type rules get in the way.

And third, at least on the PDP11, the compiler was both user-friendly (whatever you compiled took at least enough time for you to grab a cup of coffee and possibly do a printout of the source for you to look over) and economical of expression: when an error was found you were not swamped with page after page of cryptic error messages; you got a single '?' on its own line signaling clearly and completely unambiguously that you have an error somewhere in your code.

Chris Ryland said...

If you want to see how much C can shine (hmm, shining C's), compare it to BCPL, one of its antecedents. Shudder.

Anonymous said...

No Ada. Again. Sure it's not sexy, but its'a great language.

1. It was thought out. Designed. It took good idea from other languages and dumped a lot of a bad stuff. And it's very strict. C programmers may have hated Pascal back in the day because of its annoying strong typing, but Pascal has nothing on Ada. Getting Ada through the compiler can be a bitch, but that's a good thing. Catching problems early makes for less time debugging because the language let you do something stupid.

2. Runtime checks. Enumerated types, for example a variable that can be (red, green, blue), can't suddenly be assigned the value 5. An array [1..100] can't suddenly have something assigned to cell [101], because runtime checks prevent it. Not that there have been any problems with buffer overruns caused largely by bad choice of languages in the past (!cough!C!cough!).

3.Readable code. It has words like While an Loop. It doesn't just have a vague generic { and }, it has "loop " and "end loop", It has "end if". I know, I know, it's a lot of typing to put "end if" instead of "}", but if I simply show you this code:

. . . end if;
. . end if;
. end loop;

Not only is it much more readable than...
. . . }
. . }
. }

Or
. }
. }
. }
Or
. }}},

It also tells the compiler things about the structure, so that the compiler can flag up inconsistencies. It also means that if I want to, say, increment a count at the end of a loop, or chec something at the end of the loop, I can immediately see where that goes.

Anonymous said...

More Ada (or Pascal in this case)...

It has a great syntax for equality testing and for assignment. It's a little radical, it's the "=". if a = b then a:=0.

None of the "==" crap for Ada programmers.

gliderguider said...

I can't allow this slur against BCPL to go unanswered. Three things I loved about BCPL when I was using it:

- it made no bones about the relationship between an array and an index being symmetrical while C tries in vain to obscure it. In C, "a[b]" means *exactly* the same thing as "b[a]", for all possible a and b, as does "*(a+b)" and "*(b+a)". In BCPL it's just "a!b" or "b!a".

- why oh why did C drop VALOF/RESULTIS? Being able to mix statement blocks into expressions is something that every langauge should have.

- ocode was way ahead of its time. Essentially a "bytecode" like Java or the USCD Pascal p-code, and simple enough for interpretation, but intended for further compilation to machine code. It was trivial to write an ocode back end for new machines, making BCPL *extremely* portable, and to very small machines.

Jim said...

I programmed in C++ for an eternity, which in real years was 3.5. Man, I hated that language so much I was ready to dail 1-800-LUV-TRUK.

Then I discovered Objective-C, a language that, unlike C++, doesn't need books big enough to make another Great Wall of China to compensate for its inabilities, but one that takes its heritage as an OOP extension of C with grace. How else to explain a language with an instance methods that are self-documenting in its discriptive ability:

-drawImageInRect: fromRect:

or

-setTrajectoryFromPlanet:
toPlanet:
initialMeanCenterRadius:
initialOrbitType:
posigrade:
trajectoryType:
thrust:
mass:

No guessing at parameters there. And if you're sick of making your static types work out, as with C++, you can go dynamic with object type of "id". Yup, your whole program can call or return "id" and things should work out...more or less.

I may program for the Mac, a small community, but at least I don't have the nightmares of dealing with C++, and there is no price you can put on that sor of peace of mind.

JulesLt said...

The worst thing about Java is C++. It's been said elsewhere that the main reason C++ won the OO wars was that, compared to something alien like Smalltalk, it was C-enough, such that people could indeed just use it as 'a better C' while they got up to speed with OO. Not forgetting the ability to port existing C code (with some tweaking), and the fact it was N-times faster than Smalltalk or Lisp in an era when CPU performance seriously mattered in terms of application response.

Bizarrely Objective-C was actually more backwardly compatible with existing C than C++, being a strict superset, but it's OO model and syntax was more clearly in debt to Smalltalk that I suspect that put people off (there's also the fact that also meant it suffered the same relative performance issues to Smalltalk).

Java was then able to leverage the large community of C++ programmers, once they were over the OO bridge.

JavaScript - I'd disagree with your comment about JavaScript vs Flash for portable GUI clients - if you take a look at ActionScript 3.0, it's a more complete language than existing JavaScript engines (it meets the EcmaScript 4.0 prototype spec) - take a look at sites like Picnik or Adobe's Kuler as examples of what can be achieved using AS3.0 and the Flex framework, and try to imagine doing the same in JavaScript/DHTML in a way that would work on most browsers on Windows, Mac and Unix. Flex also adds MXML which is a XUL like way of declaratively defining UI. I guess the key point here is not so much the language (browser JavaScript will eventually implement EcmaScript 4.0) but the available Flash APIs (graphics and media) and speed of the VM - hence Firefox moving over to the same VM in the future for it's JavaScript engine.

Also funny to see people being against Ruby on grounds of it being hyped / fashionable, as if that reaction was any more rationally founded than leaping on bandwagon after bandwagon. The Rails hype has certainly helped raised the profile of a language that's been around for a decade without much attention.

The overall trend does seem to be towards more dynamic reflective OO programming - whether using a more pure OO language, or hacks on top of Java and C# (I do find it hard to understand the point in having a strongly typed, compiled language, then using XML files read in at runtime to work around limitations).

James Gregurich said...

C++ works just fine for those who know how to properly use it. I wouldn't write simple web apps with it, but then I wouldn't write a photoshop plugin with Ruby.

You use the right tool for the right job. If you are doing commercial desktop development or systems level programming, you certainly aren't going to use Java or Ruby or Python or any other scripting language. Your only real options there for portable development are C++ and C.

JulesLt said...

James - the interesting thing is that much of Photoshop is written in Lua (an interpreted 'scripting' language) rather than C++. You don't get a whole lot more commercial than that - maybe MS Office?

The other thing is that there's a lot of pressure against desktop applications, full stop, and towards zero-install solutions - browser based web apps. Java WebStart, XBAP (which is MS new attempt at Active-X, but this time it's sandboxed).

James Gregurich said...

JulesLt,

So?

You still need to know how to use C or C++ write a photoshop plugin...or photoshop itself for that matter.

Not everything can be a web app or written in a scripting language.

Anonymous said...

Ruby's WWW::Mechanize is not awesome it is a hack clone of perl's WWW::Mechanize missing very important functionality such as following relative links URIs (OH WAIT IT HAS TO A BE A WWW::Mechanize::LINK not a URI which it uses anyways)

Ruby's WWW::Mechanize can't handle half of the stuff the Perl's can. it is a joke and a hack.

Anonymous said...

You Forgot ColdFusion
ColdFusion,tied for the best web programming server language (much better than PHP) with Ruby on Rails, was completely left out!

Ora said...

You are wrong about Common Lisp code walkers. They don't need to understand LOOP, because LOOP is a macro (and all macros can be expanded before walking). All that code walkers need to understand about are function calls, lambdas and the 25 or so "special forms".

This, however, does not mean that it is easy to write a CL code walker... :-)

Kent said...

open-uri allow basic authentication using options as a second parameters. Also it considers urls with user name and password in them as insecure and does not allow them.

Cyril said...

Well, I hate Ruby. Comparing to Python, Ruby is eclectic and ugly. But Ruby has at least one thing done well: you can extend standard mixins. Just add a new method to Enumerable, and it magically appears in arrays, strings, intervals, anything. This is the only thing from Ruby I miss in Python.

Mathias Gaunard said...

A lot of people are commenting on C++ while they obviously don't know it.
C++ is certainly not about OOP, yet some people still believe it is C with OO capabilities.
The two good things about C++ are templates and RAII.

If you do not master those two aspects, then you cannot even remotely hope to consider yourself a C++ programmer.

While I can understand that some people can't grasp meta-programming with templates, resource management through RAII is so important that it's basically horrible to code in C++ if you don't use it.
That means each resource should be acquired in a constructor and freed in a destructor. Transfer of resources are possible through move semantics or swap functions. Sharing of resources must be done carefully, using refcounting or garbage collection.
That is to say there is no memory or other resource management that should be done "explicitly". Everything is just bound to scope with RAII.

That said, it is well known that C++ is not so good at handling dynamic typing. OOP or static visitors (with boost variant) are basically all you've got.

T. said...

Criticizing a programming language only makes sense if you've got good insight in the language. This kind of insight comes from practice - real working experience - not theory and contrived examples.

So, what projects have you finished recently in any of these languages that you write about?

SharpProgrammer.com said...

nice post but I donot completely agree with you on this !

I have looked at several programming languages.

http://www.sharpprogrammer.com
Advanced Programming Tips Tricks

Mysterious Browser said...

Now I feel the need to point something out, comparing a scripting langauge (eg, perl) to a high performance compiled language like C++ is really quite ridiculous. I mean, c'mon, how else am I going to hammer 100k+ triangles per second over the system bus to the video card?

It bears mentioning that Perl, Tcl, Ruby, Python, and YES even the Java virtual machine are all implemented in C/C++, for a damn good reason ... there's more to a language than just it's syntax, sometimes you have to get your grubby mits on the actual processer. You know, real hardware? that icky horrible dirty physical silicon that all these pretty interpreters actually have to run on ...

That said, I am a total interpreter junkie, (TCL is my reflective dynamo of choice) I just find people's critcisms of C++ utterly off base, I should know, i've written several million lines of C++ ...

Use the right tool for the right job I say.

benizi said...

I'm curious as to what you find "braindead" about Perl's string/number auto-conversion. That's one of its strongest points in my opinion.

You wrote "only context determines whether "1" and "01" are the same thing". But why is that bad? If I'm treating them as numbers, I'd want them to be ("1" == "01"), but if they're strings, they shouldn't be ("1" ne "01").

(I'm definitely biased - Perl is my favorite language. But, I'm honestly curious why you dislike this.)

taw said...

benizi: In other languages with well-defined equality/sort order you have container equality, container sorting etc. for free.

So you can do something like [["x", 5], ["y", 3], ["x", 11]].sort or ["1", 4] == ["01", 4]. In Perl you cannot do that, you have to use custom code snippets for that every time. That's really too much pain.

benizi said...

Hmm. I'd argue that your "container comparison" example is a different (but valid) objection. That was one thing I liked when I took Python for a spin.


Nonetheless, I think the 'sort' difficulty is a good justification. Having to write 'sort { $a <=> $b } @data' all the time is pretty annoying.


[For non-Perlers: the default sort is string order. i.e. 'sort @data' is the same as 'sort { $a cmp $b } @data'.]


Supposedly Perl 6's sorting will address the container concern. But, Perl 6 looks like it will be a much different beast in general.

taw said...

benizi: Container sorting and container equality are just some of the bad consequences of string-number unification. Another consequence is inability of indexing Perl hash tables by containers. In Ruby I can do ht[["foo", 5, 3.15]], indexing hash tables by arbitrary objects and arbitrary containers. In Perl there are only some painful workarounds (like stringification of objects, or nested containers).

One more bad consequence is having to do all defined($x) instead of $x when checking string data as "0" is false.

I don't see how saving a couple of string to int/float conversions is worth suffering that trouble (much more common int/float to string conversion is automatic in Ruby/Python anyway).

m0n5t3r said...

As a former Fortran, C++, PHP, and current Python and Javascript user that has also played with Java, VB, Foxpro 2.6, Perl and Ruby, some points:

Fortran (f77; f95 compilers cost money, if you can believe that...)
I liked the simple syntax, advanced IO/file parsing (try to do in C/C++ or Java something close to Fortran formats; they evolved to parse nuclear data sheets - the first free-form database ever, long before teh XML thingies) and speed; I liked less the white space constraints (reminiscent of punched card days), the way structures are defined (ugly and unreadable), the portability issues

C++
I did mostly physics (nuclear interaction simulations and data analysis), and liked it overall ('better C' type of usage, also helped a lot by the neat ROOT toolkit); had I ever touched perversions like the STL, my opinion would have probably been different :)

PHP
I like the ease of deployment and good database integration, I like less overcrowded global scope, inconsistency (not only in function naming, also in argument order), the fact that they made php5 into some sort of

Java
Liked not having to think about memory management, much better string capabilities than C, extensive library; hated verbosity and huge memory footprint of just about everything.

VB6: good: clean, simple, fit for quickly churning out Windows GUI apps; bad: tricky deployment (needs runtime installed to work, different versions can conflict, etc...)

teh old Foxpro
I don't remember much of the language (highschool is so far behind!), but I do remember the form wizard, simple syntax, decent database for small apps.

Ruby and Perl
similarly expressive, both suffering from the same problem: overuse of punctuation in syntax leads to a lot of noise which I didn't like

And now, for the present:

Python
good: clean syntax, % (sprintf as it should be), good string and list processing capabilities, decorators, 1st class functions;

bad: clumsy unicode handling (it lead to the most interesting bugs that I've produced so far :D), accepts both tabs and spaces for indenting (I am a 'tabs' guy, unfortunately Guido appears to like spaces); only worked with it for the last year or so (as opposed to 2 years Fortran, 3 C++, 5 PHP), I'll surely find more things to hate eventually :)

Javascript
actually a very nice language, plagued by the lack of a standard implementation; a while ago, when I set out to learn Scheme, I found it very easy, since I was already used to closures, passing around anonymous functions, redefining functions, building them on the fly... I'm anxious to see the ES4 out with its optional type annotation and some neat things stolen from Python, and I hope to see an implementation that lets me make my own sugar (hygienic macros ftw).

What I like less about js/ES3 is the clumsy string manipulation ("+" used for concatenation is both ugly and confusing (concatenation != sum), it has neither string interpolation, nor sprintf, no i18n), lack of encapsulation/modules/namespaces (yes, they can be implemented by hand, Lisp-style, but why?), some other things that I am forgetting now...

Anonymous said...

I don't get your problem about "self disease" in Python. There is no need to name self self. It can also be named 'peter', 'carl' or even 'Chuck_Norris'. You can even mix it, which is big fun if you share code with others... think

class Beer(object):
..def __init__(peter, s): peter.s = s
..def low(carl): return carl.s.lower()
..def hi(Chuck_Norris):
....return Chuck_Norris.s.upper()

if __name__ == '__main__':
..b = Beer()
..print b.low()
..print b.hi()

Xti said...

What a surprise... looking for information about programation, and I find a picture of MY CATS in one post about it...
¬¬

Anonymous said...

nice post !
I have a question
how to get good at programming???
I get enthusiastic about programming but even in the simplest of programs I get stuck at some places and leave it at that.
But I want to go in the programming side only as I am Comp. Science student.

Anonymous said...

how do I get good at programming?

maxTri said...

The article concentrates on older languages. I miss many new features. E.g. Multiple dispatch, closures, user defined operator symbols, etc. Language paradigms change over time. A language with extension features can be customized to new ideas. Many languages do some steps in this direction, but the only language that is really syntactically and semantically extensible is Seed7 (http://seed7.sourceforge.net).

taw said...

maxTri: seed7 looks like Pascal, and from examples you gave I don't see how it does anything interesting. You should invest some time in better examples.

And to be honest I doubt seed7 will get anywhere, for example your FAQ indicates you don't really get what closures are.

Hints: what are scoping rules here (is this call by name???), where are lambdas, and explain why closures don't work without garbage collection.

maxTri said...

Seed7 neither works like Pascal nor is implemented like Pascal. It does not follow the mainstream of Java based JIT language clones.

You want interesting examples: User defined statements (syntax+semantic), templates implemented with normal functions executed at compile-time, multiple dispatch which uses the same logic as overloading. Seed7 is defined in a library instead of hardcoded in the compiler. So replacing this library could define a different language.

It is NOT my FAQ, but the FAQ seems to explain closures used as parameters, viewed from an imperative language.

Again, not my FAQ, but I try: The scoping rules seem to be exactly the ones needed to support loop bodies and loop conditions of an imperative programming language. AFAICS it is call by name. What is the big difference between a closure and call by name?

I found no lambdas, so probably Seed7 does not need them to implement its closures and its user defined statements.

Closures don't work without garbage collection?
I am not an expert in functional programming, but AFAICS Seed7s closures seem to work without gabadge collection. Probably they are not the same as the closures from functional programming. OTOH Seed7s closures are similar to functional language closures. And they cannot be described as lazy evaluation, since the evaluation time is determined at compile time.

taw said...

maxTri: seed7 doesn't have closures. What it calls "closures" is definitely not closures, and nothing on its website indicates the author even understands what closures are, let alone how to implement them.

How about you start with defining good old map function which takes array of 'a, 'a -> 'b function, and returns array of 'b. [f(a[0]), f(a[1]), ...].

And then filter function which takes array of 'a, 'a -> boolean function, and returns array of only those elements that match the function.

And sort function which takes array of 'a, comparison function like ('a, 'a) -> boolean, and returns sorted array.

All should work on any type.

You don't even need full closures for these simple things, but figuring out these would be a good start.

maxTri said...

Don't stick with the name. Maybe it should be named differently. At least Seed7 implements something that works (see below). What name would you suggest?

I wrote a map and a filter function with a template (the sort is left out to save space). The template is instanciated for the type integer and the functions are tested with a small integer array. BTW: The map and filter functions have a third parameter, which acts as parameter for the expression.

$ include "seed7_05.s7i";

const proc: mapFunctions (in type: aType) is func
begin
const func array aType: doMap (in array aType: anArray,
inout aType: aVariable, ref func aType: anExpression) is func
result
var array aType: result is 0 times aType.value;
begin
for aVariable range anArray do
result &:= anExpression;
end for;
end func;

const func array aType: doFilter (in array aType: anArray,
inout aType: aVariable, ref func boolean: aCondition) is func
result
var array aType: result is 0 times aType.value;
begin
for aVariable range anArray do
if aCondition then
result &:= aVariable;
end if;
end for;
end func;
end func;

mapFunctions(integer);

const proc: main is func
local
var array integer: intArray is [](1, 2, 3, 4, 5, 6, 7);
var integer: number is 0;
begin
intArray := doMap(intArray, number, number+5);
intArray := doFilter(intArray, number, odd(number));
for number range intArray do
write(" " <& number);
end for;
writeln;
end func;

The interpreted and the compiled version both write the correct result:

7 9 11

The indentation in the code above seems lost. So you need to re-indent the program. Maybe I send the stuff to Mr. Mertes (and your statement that he does not know what he is doing :-) ).

Swampie777 said...

In the beginning ( high level language-wise) there was Fortran and Basic. Fortran was your bread and butter. Basic was for quick and dirty. These two needs have never gone away. The other two facets that have never gone away is the corporate view vs. the personal view. In the corporate view you wrote perfectly understandable code that anyone could copy and use and steal from you because you supported the corporate good even if you got laid off every other year. The personal view compelled you to obfuscate where ever possible to make sure no corporate bosses' jackel relative could take credit for your work, therefore preserving your job place against all political intruders. Ada was supposed to be the answer by "obsoliting" the previous hodgepodge of obscurants. C++ came along and restored the right to obfuscate. Here comes scripting langages, to restore Basic's original purpose. Why do we have all of these languages? Because programmers are like dogs. They have to put their brand on piss on everything in the neighborhood. All you need is a quick and dirty language and a bread and butter language. All languages gravitate toward being all things to all programmers anyway. So don't just pick one ( Ada). Don't let the "Chosen One" be administrated by an agency of the government( the Air Force).

So pick the simple one, and leave it alone. Pick the bread and butter one and supply it with sufficient tools to be good for the next 20 years.

It used to be spagetti code. It went to spagetti data structures. Now with all the languages,scripts, programmer ego, and esoteric up chuck, we have graduated to language spagetti.

Thanks.

Anonymous said...

I really liked your article. cardiovascular Read a useful article about tramadol tramadol

Anonymous said...

Sir, I liked your post. On the ~70% subset of languages that we both know, I share 99% of your opinions.

antred said...

C++ has its edges and it takes a very long time to become a proficient coder in C++, but __modern__ C++ (not the archaic 90s crap you see in most tutorials / books) is actually quite elegant and powerful. Personally I've coded in C, Perl, Tcl, Python, Java, C# and C++, and despite its dark corners C++ is by far my favorite (and Perl my least favorite).

taw said...

antred: I've heard the same "modern C++" argument about "modern Perl", "modern OpenGL", and even "modern PHP".

Is there any major piece of software written in this modern C++/Perl/OpenGL/PHP that doesn't suffer from all the problems of non-modern C++/Perl/OpenGL/PHP so I could check it and learn?

So far I've been unable to find the "modern non-sucky" versions.

Anonymous said...

Python is the worst language ever. Missing ends and }s is a con not a pron. You cannot even define a 2d array. And you missed the best language ever. FORTRAN.