Home > Blogs > What?s Your Function?

What?s Your Function?

By  Jul 8, 2008

Topics: Programming

For many programmers coming from statically typed, object-oriented programming languages, one of the main attractions of Python is its functional programming features. It was definitely a big draw for me so I was eager to read about functional programming in Core Python.

Before talking about Python’s functional programming features, it is good to understand the appeal of functional programming. At its (it being the appeal of functional programming as opposed to functional programming) root, it is sugar. Sure, there are a lot of interesting technical reasons, but we all love syntactic sugar. It is not that most programmers want to think in terms of functional constructs, they simply like to use a syntax that lets them write a lot less boilerplate code. Here are some obvious examples:


for (int a=1;a<500;a++){
    for (int b=1;b<500;b++){
        if (a + b + Math.sqrt(a*a + b*b) == 1000d){

t = lambda a,b : a + b + sqrt(a**2 + b**2) == c
p = lambda a,b : a*b*sqrt(a**2 + b**2)
c = [p(a,b) for a in range(1, 500) for b in range(1, 500) if t(a,b, 1000)]

The above snippets both solve Problem 9 from the Euler Project using essentially the same algorithm. The Python solution takes advantage of both lambda expressions and list comprehensions. One could argue that there is not much difference here, and that is true. Some people will not like the sugar that is used here. Others might notice that this syntax allowed all of the “magic” values (500 and 1000 respectively) to be restricted to the list comprehension, nothing in the lambdas. The lambdas are reusable. Others might also say that the one-line list comprehension reads much easier than the imperative loops.

Anyways, I had some previous experience with many of the functional concepts in Python because I had used them in other languages such as Ruby and Scala. For example, the above snippet in Scala would be:

val p = (a:int, b:int) => a*b*Math.sqrt(a*a+b*b)
val t = (a:int, b:int,c:int) => a + b + Math.sqrt(a*a+b*b) == c
val c = for {
  val a <- List.range(1,500)
  val b <- List.range(1,500)
} yield p(a,b)

Actually the above does not work ... because of Scala’s type inference system. However, you get the idea. Scala has one nice advantage over Python. There is no explicit lambda expression, the anonymous function is just like any other expression. I would say that functional programming in Scala is more natural, and is a little more “glued on” in Python. Of course Scala is statically typed, so the closures are “uglier” courtesy of the type information in the signature declaration.

This leads to the other interesting feature of Python that I was not really aware of prior to reading Core Python: generators. Here is the solution to Problem 9 in Python using a generator:

Python Generator Solution
def solver(d):
    for a in range(1,d/2):
        for b in range(1,d/2):
            if test(a,b,d):
                yield product(a,b)

for c in solver(1000):

This is really similar to the Scala solution ... but is also similar to the Java one as well. Notice that it does allow for another level of abstraction, as now the “solver” code has no hard-coded values at all. The lambda expressions were re-used, but could be moved inside the generator.