This is the second installment in what will hopefully be a longish series of explanations of problems I see with programming languages. I say “hopefully longish” because I hope to learn enough about a lot of languages to be able to continue this for some time to come, though future installments are likely to come much more slowly than these first two did.
I have some personal issues with Python that go beyond problems with the language itself, of course. For one thing, I don’t like the lack of end-delimiters for blocks of code at all. I’ve been known to say that Python makes my eyes bleed. It just looks wrong. All of that aside, however, it is of course not perfect in and of itself, as no language is perfect.
There are two things wrong with Python:
No, that’s not a typo. I really did mean to list rigidity twice. There are two types of utterly gratuitous rigidity screwing up Python.
The first is the rigidity of the language. This is actually great for teaching programming, as long as you’re trying to teach programming to students who think in a manner compatible with Python’s rigidity. It is like Pascal that way — it does things in a very carefully and rigidly structured way that helps to teach good habits to beginning programmers. Pascal was for years the de facto standard for an instructional programming language because it could teach “good habits” by way of its rigidity. As Pascal was to compiled languages in academia, so Python has come to be similarly useful amongst similarly dynamic languages.
Unfortunately, it can also contribute to tunnel vision in the student if you never let the poor student know that “good habits” aren’t synonymous with “the One True Way”. One of the marks of a true master is that (s)he knows when to break the “rules”, to discard those good habits, in favor of some elegant and unexpected solution where the “right thing” is, in fact, wrong.
Python makes that sort of thing very difficult. It does a fantastic job of dragging programming to a greater average level of elegance than Perl for instance, but to gain this it exchanges some potential for greater elegance. More to the point, however, in order to get that greater average level of elegance for programmers suited to Python use, it gives up a great deal of usability for many, many more programmers who don’t think exactly like everyone else in the Python community. That problem for many programmers is most clearly demonstrated by The Whitespace Problem. Indentation has a single Right Way in Python, and not only are you considered Wrong if you do it differently, but you simply can’t get the damned program to run. This is a problem with pretty much everything in Python. If you don’t like the way something is generally done in Python, you’re Wrong, and not only are you Wrong but your Wrong Way of doing things often won’t work, period.
The second type of rigidity screwing up Python is community rigidity, which is actually an outgrowth of the root cause of the language’s rigidity. This problem has been referred to as the Permafrost Problem — the Python community is permanently frosty to anyone that doesn’t think like the Python Collective, generally speaking. If you don’t do things the Python way — what to the Python community is the Right Way, with all other things being the Wrong Way — you’re Wrong. There are no appeals, though you may rehabilitate with dedication and contrition. It is in large part because of this second form of rigidity that the first form will probably never be fixed. Then again, maybe it shouldn’t be. As I said, it’s good for teaching good habits, and it’s still a good language the way it is. Its rigidity is useful a lot of the time.
An example of the problem of both forms of rigidity is Python’s handling of lambdas. Ruby, by contrast, allows anonymous “blocks” to be used and passed around as though they were individual discrete semantic elements. Python lambdas, on the other hand, do work similarly, but are (arbitrarily) limited to a single statement. Because of the rigidity of the community and core developers’ attitudes, that’s unlikely to change any time soon.
As with Perl, it would be nice if there were a binary executable compilation option for Python, but that’s not really endemic to the language. Python also has a couple other problems not endemic to the language: Ruby and Perl 6.
Ruby is, to many, all of Python’s benefits, none of its detriments, and some really cool bennies in addition. It’s much of Lisp’s list-handling, Eiffel’s and Perl’s syntactical ease, regexen almost on a par with Perl’s, Smalltalk’s masterful implementation of OOP, Perl’s flexibility, CLU’s iterators, and Python’s encouragement of good habits — or, more to the point, Ruby encourages and rewards good habits, while Python by contrast seems to merely punish bad habits.
Python succeeded in large part as an alternative to frustrations many had with Perl. Much of that frustration centers around such factors as the jury-rigged object oriented programming capability of Perl. It looks like the final release of Perl 6 may well sweep away pretty much all but the most superficial objections to Perl that make it unacceptable to many Python users.
I’m not nearly as familiar with the goings-on of Python development as I am with Perl or even Ruby development. For all I know, there might be exciting things happening in Python that will render all this Perl 6 and Ruby stuff irrelevant to Python’s niche, as Python might be carving out new territory for itself. On the other hand, I have a hard time imagining it doing much toward holding off its own obsolescence other than converging on Ruby, plus significant whitespace and minus flexible syntax. Maybe I just lack imagination, though.