Tuesday, June 07, 2005

Anders Heljsberg doesn't grok Python

While Debian was releasing Sarge and Steve Jobs was introducing MacX86 yesterday, Anders Hejlsberg spoke on C# at Microsoft Tech-Ed. James Avery writes:

After a couple questions from other people I was able to get in the other question I was dying to ask. What does Anders think about the resurgence in dynamic typing from languages like Python. Basically he said that he understands what benefits people are getting from dynamic typing, but he thinks they can get the benefits of dynamic typing without sacrificing strong typing. He talked about inferring type (what anonymous methods do now with delegates) and how that might be a way to get the coding speed and ease without sacrificing the strongly typed information.

Unfortunately, omitting type declarations is only a small part of Python-esque dynamism. One of the smallest, in fact. Far more important are the ability to modify objects and classes at runtime, which allow you to do things in Python that would require code generation (which is fragile, at best) or AOP language modifications to do in C# or Java.

Equally important is the attitude this fosters in the Python community: "Python assumes we're all consenting adults." "Private" restrictions are discouraged (and can still be bypassed by others if they're willing to do less work than performing ordinary refleciton requires in other languages.) As Sion Arrowsmith recently put it,:

Years of writing and maintaining others' C++ and Java code (plus one year of maintaining Python code and rather more writing) has led me to believe that there is no justification for truly private variables... [D]enying derived classes full access to your inner workings just leads to clumsier (less readable and more bug-prone) implementations derivations... [I]t's based on the hubris that you are a better programmer than anyone who might want to extend your class and can forsee all circumstances in which it might be subclassed.

This attitude of "we know better than you what code you will want to write" is found in the Java world, but it's really pervasive at Microsoft. C# methods are "final" by default; no polymorphism for you unless the original author was generous enough to specify "virtual!" This can be done in Java, but at least it's not the default. Also, huge parts of the runtime (in both .NET and Java, but more so in .NET) are "sealed," preventing subclassing entirely.

You couldn't inflict that on your users in a language like Python. Even if you could "seal" a Python class, which will never happen since it's a horrible misfeature, a user could still create his own class with the right attributes and nobody would know the difference (because of duck typing, another important part of the we're-adults-here philosophy). Well, unless you littered your code with isinstance calls, but nobody would use code THAT poorly written... if you want to play in Microsoft's world, you don't have a choice.

8 comments:

Jason Bunting said...

I like this post very much, and it gets me to thinking about these issues, which, for the most part, are swallowed whole by people that are taught these ideas because we assume someone knows better than we do (i.e. I learned many things in school that I only recently started questioning, and the importance of 'private' variables is one of them. I am not saying I don't still think they are important, but I will have to give it some thought.

The quote, "denying derived classes full access to your inner workings just leads to clumsier (less readable and more bug-prone) implementations derivations" rings true for me, as well as your mention of the fact that .NET framework classes are sealed, etc. I wanted to extend the StringBuilder class a bit, but was not able to. Instead, I wrapped it (aggregated it) in a class and although it works, it is not as 'pretty' as I would like it (i.e. not as OO as I would like it). Well, too bad Anders doesn't devote more time to looking at these matters. I think someone needs to drop him a line. Why don't you write him and more fully express these very points for him? I think it would be a good thing.

chris smith said...

"denying derived classes full access to your inner workings just leads to clumsier (less readable and more bug-prone) implementations derivations"
Has nothing to do with technical motivations and everything to do with business motivations.

Anonymous said...

As much as the opaqueness and inflexibility of C# and Java code can be vexing, it does allow them (or at least others building upon the basic structures of the language) to achieve a degree of security which Python can never hope to achieve. There is a reason the rexec and bastion bits went away...people realized that the inability to prevent access to some variables made the attempts to create a restricted execution environment a fool's errand.

I _love_ the flexiblity that the Python interpreter allows, but there are instances where it would be nice to be able to create some sort of restricted execution environment...

Jonathan Ellis said...

allowing private members has nothing to do with providing an execution sandbox.

fundamentally, rexec was killed because nobody cared enough to maintain it when problems were found. that's how open source works.

Anonymous said...

Basically what you are saying is that global variables rule, and there is rarely any need for private ones. Never heard anyone admit that before.

Jonathan Ellis said...

This is not about variable scope. You completely misunderstood.

Anonymous said...

but if we were all adults, surely things like security would be less important? but one of the principles of .NET is that code can be verifiably safe. how would you like to provide a class that implemented some security mechanism only to have a derive class decide that it wants to circumvent your security system?

"i know we're all adults here, but please, put that gun away."

sometimes its better to be safe.

Bruno said...

If your methods are final by default, the compiler can even inline the method at the call-site.

I'm not sure if an interpreter can do the same kind of optimizations. I guess this is where we all go off and read about StrongTalk, right? I think it performs runtime analysis to determine the most likely implementation at a call-site and tries to inline as much as possible.