Thursday, June 6, 2013

Functional Programming in Python

A while back, I tried looking into functional programming in Python. Most of what I saw and read made little to no sense. After spending quite some time playing with Haskell, it began to become clearer what functional programming is and how to do it. I think the main problem is that while Python can approach things from a functional standpoint, its very nature makes functional programming hard as it is not directly reflective of it.

So, the first question to be answered is what is functional programming. Functional programming is a style of programming, like object oriented, structured, procedural and the like. While languages can be designed to be more so for a specific style, you can often use other styles of programming. The two key points of functional programming is that every function must return a value and you do not want to track states. Variables have states, and these states can change. State changes are considered "side effects" and are not functional because everything needs to be constant. When things are constant, you can always expect the same output when running the same case. If the same case does not yield the same result, then it has a side effect, which is what you want to avoid in pure functional code.

Other aspects of functional style programming can include higher order functions. A higher-order function is rather useful, and if you have ever use map or filter, you've used a higher-order function. Higher-order functions will take a function as an argument and/or return a function.

Higher-order functions are very useful for making code more versatile and reusable. Notice with map, we can reuse it over and over and to change how it works, we simply change an argument and that can change its entire purpose. Folds also are in the same category, in Python it is the reduce function. The reduce function takes on a left fold.

Other higher-order functions you might have seen also take the form of decorators. While a decorator has a special syntax, it still takes a function as an argument, then returns a function. While not all decorators are functional, they are higher-order functions.

Another piece of functional programming is anonymous functions. In Python, this is using the lambda keyword. The lambda keyword creates a function that is more functional by design in that you don't store variables, there is no step-by-step procedure and the end result it returned. This is not to say you can't branch, that can be accomplished with the ternary operator. However, looping cannot be done as loops rely on states and checking of states.

So using some of the things mentioned, a quick bit of Python code in a functional design may look like this.

reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])

That is in essence, the sum function. So great, we created code that already does what other code, what's the big deal? Let's modify this a bit to get something more complex.

reduce(lambda x, y: x + y, map(lambda x: 0.5 * x, [1, 0, 0])

Like that, I've created a dot operator function (with some inputs from my perceptron post). Okay, so it looks long, so let's clean it up and create it into an actual function.

def dotProduct (weight, inputs):
    return sum(map(lambda x: weight * x, inputs))

Notice we do not store variables (ignore the argument names beings treated as variables) and we return a value. On top of that, we use the higher order function map and an anonymous function. I replace the reduce with sum because it only makes sense.

Now here's the problem, at the heart of it all, Python cannot create true functional programming. Methods like reduce, map, sum, filter and all that cools stuff, use looping. Granted if it didn't, since Python has no pattern matching syntax, if we did not use looping and fully functional recursion, each function would end up with blocks of if/elif/else statements to match the case style pattern matching.

Other "functional" programming techniques used in Python include list comprehension (modeled after Haskell's) and generator expressions (reminiscent of thunks). Python list comprehension in the root of it all is a loop. Now the reason generator expressions aren't more common, despite their ability to represent infinite data, are slow like thunks.

All that aside, functional programming. Functions must return a value, always, in every case. There must be no side-effects (if code gets too long, you can asign pieces to variables, but you must treat them as constants).

This is a broad overview of some of the key components of functional programming style. Stay tuned for more parts where I get into other stuff more specifically.

Tag Cloud

.NET (1) A+ (1) addon (6) Android (3) anonymous functions (5) application (9) arduino (1) artificial intelligence (2) bash (3) c (7) camera (1) certifications (1) cobol (1) comptia (2) computing (2) css (2) customize (15) encryption (2) error (15) exploit (13) ftp (2) gadget (2) games (2) Gtk (1) GUI (5) hardware (6) haskell (15) help (5) HTML (4) irc (1) java (5) javascript (20) Linux (18) Mac (4) malware (1) math (8) network (5) objects (2) OCaml (1) perl (4) php (8) plugin (6) programming (42) python (24) radio (1) regex (3) security (21) sound (1) speakers (1) ssh (1) telnet (1) tools (11) troubleshooting (1) Ubuntu (3) Unix (4) virtualization (1) web design (14) Windows (6) wx (2)