2016-10-19



Python is not a strict functional programming (fp) language in the sense that say Haskell is. Python includes functional programming though as well as object-oriented and imperative (aka procedural).

But it’s the functional programming aspects that I’ll be looking at here.

What is Functional Programming?

There are several facets to functional programming. The well-known one is that the application can be split into functions that don’t have side effects and it’s known as purely functional. Calling Sin(x) does not affect x or any other global or locally accessible variable. From this it follows that program state being held in a variable, a common pattern in imperative languages is not done.

In addition functions are first class citizens; typically this means what you can do with say variables can be done to functions, e/.g. passed as an argument, returned from a function, and assigned to a variable.

In a similar way higher-order functions takes a function as a parameter. In the example below, a function fact is passed into a function tracer that it then calls. Notice the nested function traced inside tracer. The function fact is passed in as a parameter to tracer and returns traced into the variable new_fact. So calling new_fact(3) calls traced(3) which calls fact(3) and returns 6.

The output is:

Iterators

If you are familiar with pointers in C/C++ then you’ll know what an iterator roughly is. It’s a way of accessing the elements of a container such as a set, list or dictionary without worrying about the underlying details. It’s a fundamental part of python.

The for statement can iterate over anything that’s iterable such as range, a “string”, the keys of a dictionary.

Generators are very good at generating iterators.

Comprehensions and Generators

One of the earliest features in Python, borrowed from Lisp (a language about LISt Processing) is List Comprehensions. It’s about creating a new list with element being the result of an operation applied to another sequence or iterable.  An iterable is an object that can return its members one at a time.

This non-comprehension example creates a list of doubles of the numbers 0 to 7.

It outputs

But we can turn it into this list comprehension:

That’s better, it’s easier to read and more importantly doesn’t leave the variable x in existence with the value 7 as the non-comprehension example does.

Generators are similar to List Comprehensions but without the square brackets. To be precise there are generator functions which return a generator object and generator expressions which evaluate to a generator object. The generator object (aka an iterator) when its .next() method is called returns a single value.

Here’s an example that prints the sum of the squares of 0-99.

There’s a bit more to generators though. They are lazily evaulated and you can have a generator that contains an infinite loop. In the example below, the generator function is called squares. This is passed a start and end value and a function to call.

The first two prints output the sum and a list of numbers (1,2) passed into isqlplus1 which returns 2x i + 1.

The third calls a lambda expression for the numbers 1-9. It’s an anonymous function that is passed in x and return x * 3.

Conclusions

Python is a great language for learning functional programming, though no replacement for fully functional languages like Haskell.  It was never intended to be functional but the designer recognizes that some aspects of fp enhances the language. If it were to be more functional it would require pattern matching, tail recursion, automatic currying and a few other features. Don’t hold your breath waiting; those won’t be added into the language though they most likely exist in importable modules.

Plus you can mix fp with the other styles. If you aren’t aware of it, take a look at the itertools module. It has many more functions that works with iterators.

The post Functional Programming in Python appeared first on Go Parallel.

Show more