0% found this document useful (0 votes)
75 views7 pages

Python FP (Slides) (2018 Loidll)

The document summarizes key properties and concepts of functional programming languages. It discusses that functional languages are referentially transparent, meaning expressions can be replaced with equal values without changing the program outcome. This allows equational reasoning and substituting equal expressions. Functional languages also avoid mutable state and side effects, instead employing recursion and higher-order functions operating on immutable values like lists. Python supports some functional programming concepts through constructs like list comprehensions, generator expressions, and built-in higher-order functions.

Uploaded by

Harry
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
75 views7 pages

Python FP (Slides) (2018 Loidll)

The document summarizes key properties and concepts of functional programming languages. It discusses that functional languages are referentially transparent, meaning expressions can be replaced with equal values without changing the program outcome. This allows equational reasoning and substituting equal expressions. Functional languages also avoid mutable state and side effects, instead employing recursion and higher-order functions operating on immutable values like lists. Python supports some functional programming concepts through constructs like list comprehensions, generator expressions, and built-in higher-order functions.

Uploaded by

Harry
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

What is a functional language?

F21SC Industrial Programming:


The distinctive feature of pure functional languages is their referential
Functional Programming in Python transparency.
Definition (Stoy, 1977)
Hans-Wolfgang Loidl The only thing that matters about an expression is its value, and any
subexpression can be replaced by any other equal in value.
School of Mathematical and Computer Sciences, Moreover, the value of an expression is, within certain limits, the same
Heriot-Watt University, Edinburgh
wherever it occurs.
Implications:
Two expressions are equal if they have the same value, e.g.
sin(6) = sin(1+5).
Value-based equality enables equational reasoning, where one
Semester 1 — 2018/19
expression is substituted by another of equal value, e.g.
f(x) + f(x) = 2*f(x)
0
No proprietary software has been used in producing these slides Scope matters: if x = 6, then sin(x) = sin(6) = sin(1+5)
Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 1 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 2 / 27

Properties of functional languages Properties of functional languages (cont’d)

Computations in functional languages are free of side effects. There is a focus on list processing. Lists are often used with
See above: these languages are referentially transparent. recursion on sublists as a substitute for loops.
Computations in functional languages are state-less. This Functional programming either discourages or outright disallows
excludes the almost ubiquitous pattern in imperative languages of statements, and instead works with the evaluation of expressions
assigning first one, then another value to the same variable to (in other words, functions plus arguments). In the pure case, one
track the program state. program is one expression (plus supporting definitions).
Functions are first class (objects). Everything you can do with Functional programming focusses on what is to be computed
“data” can be done with functions themselves (such as passing a rather than how it is to be computed.
function to another function). Much functional programming utilises “higher order” functions (in
Recursion is used as a primary control structure. In some other words, functions that operate on functions that operate on
languages, no other “loop” construct exists. functions).

Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 3 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 4 / 27
Functional languages are free of state Functional languages are free of state (cont’d)

Goal: Create a list of all square values of some integer numbers.


Imperative solution1 : Functional solution2 :

Example Example
def square(x): def square(x):
return x*x return x*x

input = [1, 2, 3, 4] input = [1, 2, 3, 4]


output = [] output = map(square, input)
for v in input:
output.append(square(v)) NB: in this version, there is no internal state; the result list is defined
in one go (bulk operation); you only need to understand the operation
NB: the contents of the list output changes as you iterate over on each element.
input; to understand the program, you have to follow the control-flow
1 2
From https://marcobonzanini.com/2015/06/08/functional-programming-in-python/ From https://marcobonzanini.com/2015/06/08/functional-programming-in-python/
Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 5 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 6 / 27

Functionally inspired constructs in Python List comprehensions

These change the way how you think about the data-structure: focus
on what the collection is, rather than how it is constructed.
Example
1 List comprehensions
combs = [(x, y) for x in [1,2,3] for y in [1,2,3] if x != y]
2 Set and dictionary comprehensions
3 Libraries of higher-order functions (map, reduce, zip) This is equivalent to this more verbose code
4 Iterators (also called “lazy data structures”) Example
Material from Functional Programming in Python, by David Mertz, combs = []
O’Reilly Media, 2015. for x in [1,2,3]:
for y in [1,2,3]:
if x != y:
combs.append((x, y))

Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 7 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 8 / 27
Generator comprehensions Generator comprehensions (cont’d)

These describe “how to get the data”, that is not realised until one A traditional, more verbose, version:
explicitly asks for it. They implement lazy data structures.
Example
Example def proc_file(file):
with open(file,"r") as f: """Find read events in an issuu log file."""
xs = (line for line in f f = open(file,"r")
if re.search(’"event_type":"read"’, line)) for line in f:
if re.search(’"event_type":"read"’, line):
yield line
NB: in this example, f is a generator, iterating over the file; you can’t f.close()
directly ask for its length

2
See this sample source code
Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 9 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 10 / 27

Set and dictionary comprehensions Libraries of higher-order functions


The most common higher-order functions are3 :
map: perform the same operation over every element of a list
filter: selects elements from a list, to form a new list
reduce (in module functools): do a pair-wise combination over
In the same way that list comprehensions are used to define a list in a
all elements of a list
bulk operation, set or dictionary comprehensions can be used to define
zip: takes one element from each iterable and returns them in a
sets or dictionaries in one construct.
tuple
Example any: checks whether any element of a list fulfills a given predicate
{ i:chr(48+i) for i in range(10) } all: checks whether all elements of a list fulfills a given predicate
takewhile: returns elements for as long as the predicate is true
This defines a dictionary, mapping digits (0–9) to their character codes. dropwhile: discards elements while the predicate is true
groupby: collects all the consecutive elements from the
underlying iterable that have the same key value
NB: in Python 3.x, all these functions are iterators; therefore, usage is
different from Python 2.x (see the examples on the next slides)
3
See https://docs.python.org/3.4/howto/functional.html
Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 11 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 12 / 27
Libraries of higher-order functions More higher-order examples

filter(test, sequence) returns a sequence, whose


elements are those of sequence that fulfill the predicate test.
E.g.
filter(lambda x: x % 2 == 0, range(10))
map(f, sequence) applies the function f to every element of
sequence and returns it as a new sequence.
map(lambda x: x*x*x, range(10))
Demo
map(lambda x,y: x+y, range(1,51), range(100,50,-1))
reduce(f, [a1,a2,a3,...,an]) computes
f(...f(f(a1,a2),a3),...,an)
reduce(lambda x,y:x*y, range(1,11))
reduce(f, [a1,a2,...,an], e) computes
f(...f(f(e,a1),a2),...,an) 3
See this sample source code
Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 13 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 14 / 27

Recursion vs. Iteration Recursion vs. Iteration

The following two versions of factorial are equivalent:


Example As a footnote, the fastest version I know of for factorial() in
def factorialR(n): Python is in a functional programming style, and also
"Recursive factorial function" expresses the “what” of the algorithm well once some
assert (isinstance(n, int) and n >= 1) higher-order functions are familiar:
return 1 if n <= 1 else n * factorialR(n-1)
Example
def factorialI(n):
"Iterative factorial function" from functools import reduce
assert (isinstance(n, int) and n >= 1) from operator import mul
product = 1
while n >= 1: def factorialHOF(n):
product *= n return reduce(mul, range(1, n+1), 1)
n -= 1
return product

Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 15 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 16 / 27
Recursion vs. Iteration The concept of “lazy data structures”

For example, the quicksort algorithm is very elegantly expressed


without any state variables or loops, but wholly through recursion: We typically think of a data structure as fully expanded data
Example In most cases, this matches the representation of data in memory
def quicksort(lst): However, sometimes we do not want fully expanded data, but
"Quicksort over a list-like sequence" still use it as a normal data structure
if len(lst) == 0: E.g. when working with large data sets, we just want to iterate
return lst over the data
pivot = lst[0]
pivots = [x for x in lst if x == pivot] A data structure that is only expanded if and when it is used, is a
small = quicksort([x for x in lst if x < pivot]) lazy data structure
large = quicksort([x for x in lst if x > pivot]) Python’s generators (and to some degree iterators) allow to use
return small + pivots + large lazy data structures
In Python 3, iterators are the preferred mechanism for
Some names are used in the function body to hold convenient values, constructing data structures
but they are never mutated
Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 17 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 18 / 27

Simple lazy Sieve of Eratosthenes Summary


Example
def get_primes():
"Simple lazy Sieve of Eratosthenes"
candidate = 2
found = [] Python borrows many of its advanced language features from
while True: functional languages
if all(candidate % prime != 0 for prime in found): List and generator comprehensions, for concise, bulk operations
yield candidate on data structures
found.append(candidate)
candidate += 1 Higher-order functions to encode commonly occuring compute
structures
primes = get_primes() Generators (and iterators) to get the benefits of “lazy data
# structures”
print(next(primes), next(primes), next(primes))
# (2, 3, 5)
for _, prime in zip(range(10), primes):
print(prime, end=" ")

Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 19 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 20 / 27
Case Study: Higher-order Functions in Python A simple example of using higher-order functions

Example
Python supports higher-order functions def my_cmp(x,y):
"""Custom comparison operator to return inverse of the defaul
This means, functions can be assigned to variables return (-1)*(x-y);
The variable can then be called like a function ...
xs = mkList(n)
See the simple histo.py sample sources from the libraries
...
slides. ys = list(xs) # this clones the input
Functions can also be passed to other functions to modify the ys.sort() # this sorts the list
behaviour zs = list(xs)
zs.sort(key=functools.cmp_to_key(my_cmp)) # comp. function
One concrete application of this is modifying how sorting works
...
The sample code is in ho sort.py. zs = list(xs)
zs.sort(key=functools.cmp_to_key(gcd_cmp)) # comp. function

3
In Python 2 use: zs.sort(cmp=my cmp)
Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 21 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 22 / 27

Towards the CW
Documents Readers

Input

Also read ...


An example closer to the CW is this:
Top result (most also readers)
We have a list of persons, and each person has a set of favourite
numbers Other results
We want to compute what is the most favourite number, i.e. one
that appears most often in the favourite sets
Note, that this structure is very similar to Task 5 in the CW

Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 23 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 24 / 27
Towards the CW Simple solution to “favourite number”

Example
def mostFavNum(dict):
"""Return the most favourite number."""
In our favourite number example # we use sets to collect the numbers
xs = set([])
we have numbers instead of documents (as circles)
# iterate over the dictionary entries
we have names instead of readers (as boxes) for k in dict.keys():
the structure of the computation we need to do is similar to the xs = xs | set(dict[k])
coursework # decorate each number with the matches, and use this as 1st
xs_dec = [ (countMatches(x,dict), x) for x in xs ]
# sort the list by first component in the tuple (no of matche
xs_dec.sort()
# return xs_dec[-10:-1] # return largest 10 values, if you p
n, x = xs_dec[-1] # largest elem
return x # return it’s value

Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 25 / 27 Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 26 / 27

Higher-order version

The basic idea is to turn countMatches into a function


argument
Then in the main part of the code you just need to call:
Example
print(mostFavNumGen(favs,countMatches))

You can check the full code at ho sort.py.


Use this as an example how to tackle Task 5 in the CW.

Hans-Wolfgang Loidl (Heriot-Watt Univ) Python Functional F20SC/F21SC — 2018/19 27 / 27

You might also like