Log in

No account? Create an account

Fri, Oct. 16th, 2009, 10:26 am

This post unintentionally demonstrates that functional-style Python is ugly and bad.

Let us start at the top. At the beginning, it has some sample code which defines a multiple() function, which could be trivially inlined, resulting in code which looks like this (I'm doing all examples in Python 3):
print(sum(x for x in range(1, 1000+1) if x % 3 == 0 or x % 5 == 0))

There's no reason whatsoever to expand that out. This should be an early indication that maybe the code samples here aren't the greatest.

Moving on, there's getting the sum of all fibonacci numbers less than 4 million. This is done in the example using itertools and yield, resulting in a fair amount of ugly code. Here's how a sane person does it:
def fibsum():
	a, b, c = 0, 1, 1
	total = 0
	while c < 4000000:
		total += c
		a, b, c = b, c, b + c
	return total

Now that's much more readable, flexible, and maintainable.

Finally, there's the problem of finding the largest palindrome which is the product of two three digit numbers. Here's my solution, which contains less code, is much more readable, and oh yeah, I threw in an optimization to make it return almost instantly instead of having to crunch for a second:
def bigpalindrome():
	best = 0
	for i in range(999, 0, -1):
		if i * 999 < best:
			return best
		for j in range(999, i-1, -1):
			x = list(str(i*j))
			if int(''.join(x)) == i*j:
				best = i*j

Much better. I think these examples do a good job of exploding the idea that the functional style of programming is clearly better and the appropriate first thing to teach people. Obviously some people are being driven to write horribly contorted and ugly code because they started in a functional language when they switch a more, ahem, mainstream one.

Sat, Oct. 17th, 2009 08:13 pm (UTC)

My post doesn't contain any comments about the clojure code whatsoever.

Sat, Oct. 17th, 2009 08:36 pm (UTC)

No, but you extrapolated the poor python code to statements about all functional languages.

Sat, Oct. 17th, 2009 09:27 pm (UTC)

You should go re-read my post a bunch of times until you actually parse what I said

Sat, Oct. 17th, 2009 11:21 pm (UTC)

All right, I did misread your post. I still disagree with your conclusion about thinking like a functional programmer/teaching functional programming to beginners. One certainly needs to be careful when trying to apply functional techniques in a non-functional language. While the python code is pretty indefensible, it does demonstrate that the programmer is thinking about the extensibility of his program. Yes, he has to bend over backwards to implement lazy lists, but the end result (assuming that pile of code ends up allowing him to write code like the Clojure sample) is that he has a modular way to process the fib seq, in the same way that the Clojure sample does - something your code does not accomplish. He's guilty of swinging for the fences when he should be bunting. But the functional thinking can also lead to nicer code (the Clojure sample is much cleaner than any of the imperative code you wrote). This tells me that the functional approach has its merits.

In my experience, programming in a functional language allows the programmer to concentrate on the problem that needs to be solved rather than the details of how the computer is going to handle the data. This is a trait that we should be fostering in all programmers. I think this code suggests:

1. We should also do a better job of teaching people to program in imperative languages (I would say AFTER we teach them how to think in functional languages). This would mean finding more robust ways to translate functional ideas into imperative languages.

2. Mainstream languages would do well to develop some libraries/extend their syntax to support functional ideas in easier ways. The lazy-list handling code should be moved into a library for example to allow the python programmer to use it to write cleaner code in other places. But more generally, they need better/more succinct abstraction tools. As you pointed out in another post, using classes/objects is often like hammering in a nail with a file cabinet.

3. We should develop ways to compile functional languages into mainstream languages. That way, people who grow up thinking functionally (a good thing) can make an easier transition into working with mainstream languages when they enter the workforce. I've been told that there is a well optimized Scheme->c/c++ compiler that gets very good performance (although it is quite slow in the compile time) out of the final code.