Functional Python Programming

(Wang) #1
Chapter 2

Here is TCO done as a generator expression:


def isprime(p):
if p < 2: return False
if p == 2: return True
if p % 2 == 0: return False
return not any(p==0 for p in range(3,int(math.sqrt(n))+1,2))

This function includes many of the functional programming principles, but it uses
a generator expression instead of a pure recursion.


We'll often optimize a purely recursive function to use
an explicit for loop in a generator expression.

This algorithm is slow for large primes. For composite numbers, the function often
returns a value quickly. If used on a value such as M 61 =−2 1^61 , it will take a few
minutes to show that this is prime. Clearly, the slowness comes from checking
1,518,500,249 individual candidate factors.


Functional type systems


Some functional programming languages such as Haskell and Scala are statically
compiled, and depend on declared types for functions and their arguments.
In order to provide the kind of flexibility Python already has, these languages
have sophisticated type matching rules so that a generic function can be written,
which works for a variety of related types.


In Object-Oriented Python, we often use the class inheritance hierarchy instead of
sophisticated function type matching. We rely on Python to dispatch an operator
to a proper method based on simple name matching rules.


Since Python already has the desired levels of flexibility, the type matching rules
for a compiled functional language aren't relevant. Indeed, we could argue that
the sophisticated type matching is a workaround imposed by static compilation.
Python doesn't need this workaround because it's a dynamic language.


In some cases, we might have to resort to using isinstance(a, tuple) to detect if
an argument value is tuple or an individual value. This will be as rare in functional
programs as it is in Object-Oriented Programs.

Free download pdf