Saturday, June 27, 2009

Why Python (1)

In this post, I rant about why Python is superior to languages such as Java / C++ , and currently I am not debating over other similar languages such as Ruby.

The first, and most important thing in Python is that simple things are simple:


print "Hello world"


The equivilant Java looks like:

public class HelloWorld {
public static void main(String [] args) {
System.out.println("Hello world");
}
}


I find this a crucial point in coding, since often what we are doing is a collection of simple tasks. Another concept that is visible here, is the amount of boilerplate and unneeded structure that we are forced to embark on. We don't want a class, we don't want a function, we don't want the command line arguments, but they bloat our code's structure. I also find the notion of using a 'class' instead of a 'bundle of functions that work together' very annoying, which is common in traditional languages.

To continue ranting on the above differences, the style of Python is multi-paradigm. It means I can chose to code OO, if I really need it; otherwise I can keep things simple.

Another feature of Python that I find crucial is it's interactive mode. It serves as a toybox where you can test language features (if you forget), or simply play around with a new API, often exploring objects and their documentations. In general, I note this feature most critical for teaching programming languages (I will put on another rant why I find Python a much better language for teaching than languages such as C or Java).

The next important feature of Python is "duck typing". Suppose you want to write a code that will interact with a specific method of an object. In traditional non-duck typed languages this will often set up some sort of inheritance hierarchy and will require the user of this function to "inherit" from the superficial supertype, or "implement" another superficial interface. Why I describe them as superficial is that we often only use a portion of the interface, but are imposing the end user to implement all (unneeded) methods. This design bloat often propagates through inheritance and composition and the result is a lot of what I previously described as unneeded structure.

This is not elegant coding style, and is even visible in the Java library itself, for example consider Thread class or Runnable or Comparable or many such interfaces that can simply cease existing through duck typing. Compare such interfaces with placing the ugly toString and hashing methods in Object parent.

The fact that I find single-inheritance also very ugly and the concept of interfaces to fix-up this issue a very ill solution, and also the single-root hierarchy a more ill excuse to have single-inheritance, may be a reason I'm all for duck typing. (Not that I'm against the single-root one, but it's not an excuse for single-inheritance). The introduction of generics in Java was a language modification to fix-up the ill results of applying this ill method.

There is one criticism against duck typing which states that in this mode coders much be aware of a larger section of how things work in the code. I find this useful.

Also in Python there is dynamic typing. This is often confused with weak typing which is done in javascript and php (which I don't favor). Weak typing is for performing automatic type conversions (such as adding strings and integers), and allowing aliasing (like pointer castings in C). Such behavior is disallowed in Python. Static typing provides the user with a false sense of safety. The amount of debugging and first-time-failures involved in such languages show that their type system is very inadequate. It often introduces lots of code bloat as well. To exactly nail the point, I will state it like this: Much of the code written is just to keep the compiler to shut up; and when it does shut up, it doesn't mean the problem is solved. It is important to note that the type system may reject some perfectly correct code.


Dynamic typing must be backed with testing. It is important to notice (as Bruce Eckel does on his blog), that the entire type system is just one (often unnecessary) test. In my point of view tests are the only way to ensure we are not creating a large box of bugs and breaking things instead of fixing them during coding, so they have to be there anyways, and will catch type errors very soon.

In Python, the concept of binding is best understood in the terms of 'names', not in the terms of variables, pointers, references, etc.. There are names (in our code), and objects (at run time). It's really as simple as that. (I will explain a little about it later.)

These concepts may have brought me to Python, but arguably Ruby also provides a lot of the same kind of stuff and is even more powerful in some aspects. What has kept me nailed to Python is the sheer readability of Python code. When you read Python code, the meaning of the code is sharp as a blade. It's just crystal clear. One major cause of this is forcing using indentation in code structure. (Yes, I was caught once more by the dangling else bug a couple days ago and yes it was Java)

Short code is important. Less lines of code mean less bugs. Less places to make silly mistakes. Python let's me focus on the business issue, not the language constraints.

Another important feature that keeps code short and compact is built in dictionary and list types. Compare what:

x = [10,30,55,40]


looks like, to what:

ArrayList<Integer> x = new ArrayList<Integer>();
x.add(10);
x.add(30);
x.add(55);
x.add(40);


looks like; and always what we are putting in these data structures (lists and maps) aren't integers, and the code looks uglier in the latter case.

I will continue on this rant in a further post.

No comments:

Post a Comment