Summary
I'm glad to see the first beta of the so-called Python 3000. But for a version that's supposed to break all the rules to become better, I'm not seeing what I think is most important.

Advertisement

As time passes I appreciate Ruby more and more; hats off to Ruby, it (via Rails) has brought dynamic languages into the mainstream. But I've spent far more time with Python so I'm still much more productive with it, and remain a huge fan of the language.

Because I'm invested in Python, there are things I hoped to see when Guido first started talking about Python 3K and how it had permission to completely change the rules in order to create a better language. We did this once before in Python 2.2 or 2.3: introduced backwards-incompatible changes that would break old code. I remember there was a lot of trepidation and concern and scaffolding to try to gentle the transition.

But it turned out to be a non-event. The people who didn't want to change stayed with the earlier version of the language, and those who moved forward saw the costs and the benefits, and opted for the benefits. Apparently Ruby is also planning code-breaking changes to the language, primarily to take out the Perl-isms (a move I heartily applaud, and one that makes Ruby that much more attractive). And the Java designers should certainly take notice, especially because the people they are so worried about offending with language incompatibilities are still using Java 1.1 with no plans to change; they aren't even paying attention to these discussions. In the meantime, Java continues to ossify, pursuing its endless quest to produce the perfect program through static type checking, by adding more and more. The good thing is that people are finally beginning to see that static type checking is useful in small amounts and intrusive in large amounts (although I suspect this realization won't reach the main group of Java designers for years to come). The bad thing is that, in the meantime, we get abominations like Java "generics"; via daily use people are finally beginning to see what I tried to explain years ago -- Java "generics" are far more painful than helpful, just like checked exceptions. But I digress.

In this article I talk about the issues that I consider very important, and worth code-breaking language changes, that I don't see happening in Python 3K.

I know that true concurrency support -- the ability to run pieces of a program on multiple processors -- is hard in a dynamic language. Although they both have threads, neither Python nor Ruby is able to actually allocate those threads to multiple processors. The threading is just for code organization and to handle blocking operations. Ruby and Python are prevented from using multiple cores because they both suffer from the global interpreter lock problem.

But right now we are on the brink of a huge potential gain for dynamic languages, with the advent of multi-core systems. Here's the place where the performance impact of dynamic languages, so often used as an excuse to avoid them, could be erased. Multicores could be what brings dynamic languages into their heyday, and could relegate languages like Java and C++ as "what you use for writing small pieces of your application, only if you absolutely must."

The solution can be creative, as long as (A) it's simple to use and (B) it's reasonably idiot-proof; I'm the first to admit that I'll probably never be able to create a correct threaded program in C++ or Java, despite years of study. It's just too hard.

From a programming standpoint, agents are still the best thing that I've seen. The language provides support to help the programmer create agents, and for the agents to automatically handle their own concurrency and defend their memory. There's no shared memory outside the agent, every change happens via an input queue, and each message is executed to completion rather than trying to execute multiple messages together. See the Scala Language for more details on agents.

One solution I can imagine that might work is to take the BeOS operating system's approach, which is to make creating OS processes very easy. If there's no way to get rid of the GIL even in Python 3K (but there might be a way, given enough language changes), then perhaps it would be possible just to create a new Python image in another process, and make it easy to communicate with that process. Thus, creating an agent would create an OS process, and communicating with the agent would actually send messages through OS pipes.

That's just one suggestion, but the problem needs to be solved or some other dynamic language will solve it, and we'll be forced to go to that language in order to use all the cores that are becoming available (Scala agents have already produced what seems to be the best solution around, especially because Scala has tried to solve the syntax-horror problems that plague traditional functional languages -- and yes, before you write, I've looked at Erlang, which is great at solving some problems but it isn't the future that Scala promises).

I know it's hard. But I don't want to hear that it's impossible to fix the GIL. I don't care, I need to run programs that use multiple cores and I'd sure like to use Python to do it.

I'm hoping that this is just an issue of "waiting for maturity," but we need to make support for Python Eggs and Easyinstall part of the python distribution. Easy installation and update of library components should not require effort or be a distraction.

This is connected to the previous point, but it's important on its own. We need a one-button solution to deploying applications, producing a package that gives consumers a one-button solution to installing them. Too many people have avoided Python apps the same way they avoid Java apps, because the installation process is confusing. And don't tell me "it's not hard!" Yeah, it's not hard for you, the computer geek, you love doing stuff like that (recompiling your Linux kernel seems like the most obvious thing in the world to you). But the average user gets flummoxed the first time the install process asks them a question, and forget it if it involves multiple steps and installations.

This is something I really hoped to see in Python 3K, but the beloved self seems to be hanging on.

self is inappropriate noise in a language that lays claim to clarity and simplicity. No other mainstream OO language requires it everywhere like Python does, and it's a hurdle for people who try to come to Python from those languages. Maybe it's a significant reason that Java programmers seem to be more comfortable with Ruby; Ruby takes care of it for you just like C++ and Java do.

Although it still gets use, I don't think the built-in Tcl/Tk would be anyone's choice as a standard Python UI library if we were deciding today. This is especially true when you look at systems like Flex and Silverlight (and presumably JavaFX, but I haven't yet seen that), which are designed to solve the UI problem first.

Why not create the best of all possible worlds and leverage those systems -- optimized to create UIs -- on top of Python the same way that we've used Tcl/Tk in the past?

Event support, described below, would probably make this a lot nicer, but I'd at least like to see a solution that allows me to transparently talk back and forth to the UI subsystem in my application.

Reusing library components is still the most productive way to leverage any programming system, and Python has always made it far easier to use libraries than most other languages I've worked with -- certainly much easier that C++ or Java. I'm used to using a text editor because even naked, the language is vastly more productive than Java, but people have come to expect a much more interactive development experience. IDEs with context assistance may seem like icing on the cake, but they really do increase productivity and Python 3K is the place to support this.

We've only scratched the surface of what's possible with an interactive software development system, and most of these are variations of a single idea: context help. But context help is just a slightly smarter version of online help -- it removes a step from the searching process, and will sometimes paste in rudimentary code fragments for you. Although that's been extremely useful, I think it's possible to create a far more revolutionary development environment, one that could even be said to practice "inversion of control."

I think the libraries themselves need to get smarter and support greater interactivity. I want the component to tell me what it does, how to use it, and even to reach out and wire itself into my program (for example, by looking at the available variables and putting candidates into its argument list, with drop-down menus that allow you to select appropriate alternatives). In the best of all possible worlds I would never have to look up documentation for a library component again, because the component would insert itself properly into my program and answer any questions that I have by itself, without me looking anything up -- for example, if it was missing an argument, it could suggest the way to create the object that it needs for that argument.

The information necessary to create a "smart library" is in the same vein as JavaDoc; a little language that allows you to expose information about your library component. But JavaDoc is really an early experiment, and I think we should standardize the way that you describe the information that your component exposes to a development environment, and even the way it does command-completion. This way you could hover your mouse over an identifier and do all kinds of things to it.

I think it would even be possible to integrate tests into the library component, maybe deeper tests that could test the way that you've used the component. But even if the new approach just provided tighter coupling with unit tests (and ideally, a less noisy syntax for unit tests), that could be a great improvement.

Optional static typing, similar to what Flex uses, seems to be in the works for Python 3K, although Guido has cleverly disguised it as "any information that you'd like to add, doesn't have to mean anything." This may solve a major part of the problem with Python as it does with Flex -- the FlexBuilder development environment gives you warnings (and doesn't provide extra information) when you don't provide the optional static typing, but programs compile just fine without it. With the extra type information, you get context assistance in the IDE.

I've been using the word "component" rather loosely; true component support seems to require direct language support for properties and events. Although it's not formal, Python has a decent property mechanism, but event support is not a part of the language and is relegated to third party libraries like Twisted, which is interesting but hard to pin down (I spent a few weeks once working with what I thought was the main thrust of the Twisted library, only to discover that the creators had decided that was a dead end and were working on something else).

As mentioned before, there is no really official UI library for Python, so there hasn't been pressure to support an eventing system that would make it easier. And I don't even know if that's a good idea -- with support for simple coupling to Flex, Silverlight and JavaFX we may forever remove the need for Python to have its own UI library.

But in general, if each Python process does indeed need to be single threaded from a processor standpoint, then built-in eventing could at least help produce the organizational effect that you get from breaking a program up into individually running pieces.

Although Domain-Specific Languages (DSLs) have gotten a lot of press lately, creating little languages to solve specific problems has always been one of the more powerful weapons in a programmer's toolbox (the Interpreter design pattern is an example of this). This is another area where Ruby has a leg up, although in the grand scheme of things Ruby's DSL support is fairly limited.

There's even a new language called Converge, inspired by Python and with Pythonic syntax, that is primarily designed to create DSLs. This could be used as inspiration for native DSL support in Python 3K.

I agree with your point about the GIL. It's a big stone in the way to worlddomination for Python. Unfortunately the chances for getting rid of the GILseem to be the same as the chances of Stackless getting merged.

Setuptools would indeed be a nice to be addition to the standard library and Ithink it will be merged at some point in the future.

Regarding DSLs: I think creating DSLs is against the Python's philosophy. A lot of things you would normallyneed a DSL for can be solved very elegantly throughfeatures like metaclasses. Support for the latter is greatly improved in Python 3000.

Regarding self: I think the tight connection between functions and methodsthat is the reason for the implicit self is one of the features that makesPython so easy and yet powerful. Getting rid of it would make the source codemuch less readable ("Where does this variable come from?") and would probablyprevent many of the cool things that are possible now.

It seems that things like smart libraries, events, components, (and partly optional typing, though not static), are achievable without language changes, just via libraries. Same applies to a GUI library. Thus, work can be done in parallel.

All 'smart' things need a smart environment to work. IDLE is OK but no peer to smart Java tools. (OTOH, smarts come at a price; an Idea installation is many times larger than an entire Python installation.)

Getting rid of 'self' is not so easy; I personally got used to 'self' in instance methods and 'cls' in classmethods, but the difference is a mere decorator; with metaclasses things become even more complicated. Grafting 'naked' functions into classes/objects (as decorators often do) makes this next to impossible. Python seems too dynamic to get rid of 'self' %)

GIL is a pain; there's Stackless Python that lacks it, along with some other important features, alas.

On the subject of threads it seems like one possible solution is to have a library that integrates a certain amount of forks with threads automatically. I know this isn't best, but is much more doable for the here and now.

> But Ruby -- and they argue that it's even more dynamic> than Python -- doesn't have self.

In my opinion it's easy to hack away in Ruby really fast.But one big problem is that it's really difficult get a full understanding of the language. There a many things that are suprising, inconsistent or plain ugly.

self is just another instance where Python is explicit instead of implicit. Why would you want to have an implicit self in Python? Do you just want to type less? That's what editors are for. Or do you not want to have to know wether a variable/function is local/global or belongs to the object? This is a bad thing, IMHO.

> self is just another instance where Python is> explicit instead of implicit. Why would you want to have> an implicit self in Python? Do you just want to type> less? That's what editors are for. Or do you not want to> have to know whether a variable/function is local/global or> belongs to the object? This is a bad thing, IMHO.

But isn't the "power" so often mentioned about Python/Ruby computed as (things you can do / typing required to do them)?

Trivializing the desire to type less code is the same technique that Java programmers use when defending the verbosity of the language. Editors should be a convenience, not a necessity to avoid carpal tunnel and/or insanity.

I feel obliged to say this before I continue: I love Python.

But the two things that bother me the most about Python these days (in comparison to Ruby, of course) are the lack of Gems and the lack of Rake.

Now, I know we have setuptools or eggs or easy_install, but they're just not good enough. First off, easy_install is a terrible name. And it needs to be able to easily search for eggs and upgrade all currently installed eggs.

Also, the lack of a Rake-like tool hurts badly. I'm currently writing my own custom commands using setuptools in setup.py, and it works, but it's much more involved and verbose than writing Rake tasks. How can I easily build my docs, or run my tests? It's too much work.

I may end up writing patches to try and fix this stuff, but in the end, I sometimes wonder: is it even worth it when I could just switch to Ruby and get on with writing my real application?

> Trivializing the desire to type less code is the same> technique that Java programmers use when defending the> verbosity of the language.

Exactly, and it's not the writing but the reading. Python generally makes code that's easier to read, but 'self' is an intrusion.

And parroting "explicit is better than implicit" is a misuse of that maxim. All languages provide abstractions; Python (generally) produces clear abstractions that tell you what's going on -- these abstractions are explicit in "the right places." But 'self' is something we don't need to see inside classes. You're in a class, so 'self' or 'this' can be implied, just as it is in every other OO language I know of. Ruby, I think, has it right on this one.

> Also, the lack of a Rake-like tool hurts badly. I'm> currently writing my own custom commands using setuptools> in setup.py, and it works, but it's much more involved and> verbose than writing Rake tasks. How can I easily build> my docs, or run my tests? It's too much work.

I've long wanted something with 'make' dependency syntax, but Python rules. I know there have been a few attempts, but nothing that clean. The answer might be just to go in and hack a copy of the Python interpreter. Even better if there could be a flag on standard Python that would invoke make-like activity, so you could just run "Python -make."

I am beginning to think that JRuby will propel Ruby to new heights because it will give it all of the benefits of running in a JVM (libraries/app servers) and access to its threading facilities. Scala also runs in both JVM and .NET. Why not take the same approach to Python 3K?

> Also, the lack of a Rake-like tool hurts badly. I'm> currently writing my own custom commands using setuptools> in setup.py, and it works, but it's much more involved and> verbose than writing Rake tasks. How can I easily build> my docs, or run my tests? It's too much work.

I have been using BuildIt to write the equivalent of Rake tasks. It doesn't have the adoption of Rake, but it's an excellent package that I'm quite happy with:

There is still room for improvement in the easy_install and eggs area though.

Python has been making lots of ground in the area of build tools of late. zc.buildout, BuildIt, and workingenv all provide good ways of installing the parts that you need to develop a complex web application. You can't do "rake install rails" on a clean system and then start developing (or maybe you can now?), but you can do "easy_install plone" or "easy_install grokproject" and get a complete system.

Guido allowed breaking of backwards compatability for Python 3, but the purpose behind this was to make it easier to clean up the early design warts of Python, and not to introduce new approaches or paradigms to the design of Python itself (i.e. implicit self). Python has always been quite good at moving incrementally forward every year or two, while still maintaining backwards compatability. But this approach has come at a cost, as the amount of cruft to deal with historical warts in the Python 2 code base has been growing every year. Python 3 just gives the core devs the opportunity to make the CPython implementation a lot cleaner and more maintainable. Hopefully this in turn will make it easier for alternate implementations such as Jython and IronPython to maintain better implemenations of the language as well. Taking the warts off of Exceptions, Imports, Unicode and short/long ints are really the kind of clean-up that Py3K is targeting. They are not glamorous or radical changes, Python is still the same old Python, it's just a cleaner, more pleasant Python.

As for my wishlist, I'd put more clean-up to the standard library at the top of the list. But I'd also like to be able to migrate Python code from 2 to 3 without having to revisit every line of code, and I'd also like to be able to see Python 3.0 final ship in a timely manor - and I think the Python dev team are doing a very good job at managing both of these factors. The amount of clean-up that is happing to CPython over the Py3K development timeline is really quite impressive, especially considering that Python development is almost entirely driven by open source community efforts.

> And parroting "explicit is better than implicit" is a> misuse of that maxim. All languages provide abstractions;> Python (generally) produces clear abstractions that tell> you what's going on -- these abstractions are explicit in> "the right places." But 'self' is something we don't need> to see inside classes. You're in a class, so 'self' or> 'this' can be implied, just as it is in every other OO> language I know of. Ruby, I think, has it right on this> one.

But this scoping is explicit in Ruby as well; you merely say @foo instead of self.foo

I understand preferring @foo (even though I personally prefer self.foo), but it doesn't seem terribly different to me.