Tuesday, June 30, 2009

Why Python (2)

The next features of Python that I chose to rant on are ones that come from functional languages. These are what provide a lot of power and short syntax to Python. The first and most important of them are first order functions. This allows us to treat functions as any other normal argument or return value, which is an important concept that allows us to write smaller code with "high order functions", or functions that take functions as arguments. The full support of closure adds to this feature.

def adder(n):
def f(x):
return x + n
return f
f = adder(4)
print f(3)


This is an example of a function returning a function and taking a closure. This behavior is also somewhat possible in Java if we use syntax like:

class Demo {
public void test() {
Adder t = new Adder(4);
System.out.println(t.f(3));
}
}

class Adder {
private int n;
public Adder(int n) {
this.n = n;
}
public int f(int x) {
return x + n;
}
}
but it seems somewhat awkward; this method will also introduce an interface or abstract class into our type system for each time we want to do this.
In particular there are some important high-order functions in functional languages such as map and filter. Map takes a list and a function and applies the function to all of the elements of that list. Filter takes a list and a function and returns a list containing elements that cause the function to return true. Python provides support for these functions and a special shortcut for it called list comprehension. See this example:

L = [x+2 for x in L if x > 0]


This small example would looks very weird in Java, since it would involve removing items from a list and otherwise appending 2 to them, a simple thing that comes to mind is:

for (int i = 0 ; i < L.size(); ) {
int value = L.get(i);
if (value > 0) {
L.set(i, value+2);
++i;
} else {
L.remove(i);
}
}
This is exactly one of the most important ways that Python looks better than such languages, and the difference is real, consider quicksort:

def quicksort(L):
if L == []:
return []
key = L[0]
return quicksort([x for x in L if x < key])
+ [x for x in L if x == key]
+ quicksort([x for x in L if x > key])

This it a copy paste quicksort implementation I found on the net for Java:

int partition(int arr[], int left, int right) {
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
};
return i;
}

void quickSort(int arr[], int left, int right) {
int index = partition(arr, left, right);
if (left < index - 1)
quickSort(arr, left, index - 1);
if (index < right)
quickSort(arr, index, right);
}
This difference in length of code and obviousness of what is going on will present itself in real situations.

This rant will continue.

No comments:

Post a Comment