Introduction to Higher Order (Functional Programming) (Python) part 2

Slides:



Advertisements
Similar presentations
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 14 Functional Programming It is better to.
Advertisements

Expressions and Statements. 2 Contents Side effects: expressions and statements Expression notations Expression evaluation orders Conditional statements.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
1 COMP 144 Programming Language Concepts Felix Hernandez-Campos Lecture 21: Functional Programming in Python COMP 144 Programming Language Concepts Spring.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 14 Functional Programming It is better to.
Functions in Python. The indentation matters… First line with less indentation is considered to be outside of the function definition. Defining Functions.
List Comprehensions. Python’s higher-order functions  Python supports higher-order functions that operate on lists similar to Scheme’s >>> def square(x):
Computer Science 209 The Strategy Pattern II: Emulating Higher-Order Functions.
Introduction to Functional Programming (SCALA) John Woodward.
Data Structures Akshay Singh.  Lists in python can contain any data type  Declaring a list:  a = [‘random’,’variable’, 1, 2]
Com Functional Programming Higher Order Functions and Computation Patterns (I) Marian Gheorghe Lecture 10 Module homepage Mole &
Haskell Chapter 1, Part I. Highly Recommended  Learn you a Haskell for Great Good. Miran Lipovaca.
Clojure 4 Sequences 20-Oct-15. Clojure errors (NO_SOURCE_FILE:12) Useless--just means you’re running from the REPL shell java.lang.Exception: EOF while.
 Expression Tree and Objects 1. Elements of Python  Literals, Strings, Tuples, Lists, …  The order of file reading  The order of execution 2.
8 For-Statements © 2010 David A Watt, University of Glasgow Accelerated Programming 2 Part I: Python Programming 1.
Robert Vitolo CS474.  Branched off of ML (metalanguage)  Developed at Microsoft, available as part of the Visual Studio 2010 software package, integrated.
Built-in Data Structures in Python An Introduction.
Functional Programming With examples in F#. Pure Functional Programming Functional programming involves evaluating expressions rather than executing commands.
Functional Programming in Scheme and Lisp.
Iterators, Linked Lists, MapReduce, Dictionaries, and List Comprehensions... OH MY! Special thanks to Scott Shawcroft, Ryan Tucker, and Paul Beck for their.
Going Functional Primož Gabrijelčič. Functional programming.
Computer Science 111 Fundamentals of Programming I Default and Optional Parameters Higher-Order Functions.
Curry A Tasty dish? Haskell Curry!. Curried Functions Currying is a functional programming technique that takes a function of N arguments and produces.
Midterm Exam Topics (Prof. Chang's section) CMSC 201.
Haskell Chapter 5, Part II. Topics  Review/More Higher Order Functions  Lambda functions  Folds.
C H A P T E R E I G H T Functional Programming Programming Languages – Principles and Paradigms by Allen Tucker, Robert Noonan.
Python Basics 본 자료는 다음의 웹 사이트를 정리 한 내용이니 참조 바랍니다. ythonBasics.
Functional Processing of Collections (Advanced) 6.0.
MapReduce, Dictionaries, List Comprehensions Special thanks to Scott Shawcroft, Ryan Tucker, and Paul Beck for their work on these slides. Except where.
1 Introduction to Functional Programming in Racket CS 270 Math Foundations of CS Jeremy Johnson.
Introduction to Concepts in Functional Programming CS16: Introduction to Data Structures & Algorithms Thursday, April 9,
Functional Programming in Python Abhishek Dasgupta Indian Institute of Science Education and Research, Kolkata.
Functional Programming
Fundamentals of Programming I Higher-Order Functions
String and Lists Dr. José M. Reyes Álamo.
Functional Programming
Higher Order Functions
COMPSCI 107 Computer Science Fundamentals
6.001 Jeopardy.
Functional Processing of Collections (Advanced)
Introduction to Functional Programming in Racket
Main Points of Haskell Functional programming Laziness
CHAPTER FOUR Functions.
Important Concepts from Clojure
Important Concepts from Clojure
Higher-Order Procedures
Functional.
Arithmetic operations, decisions and looping
LECTURE 31: INTRO TO FUNCTIONAL PROGRAMMING
Clojure 4 Sequences 27-Nov-18.
Clojure 4 Sequences 5-Dec-18.
CSCI 3328 Object Oriented Programming in C# Chapter 5: C# Control Statement – Part II – Exercises UTPA – Fall 2012 This set of slides is revised from.
CSE 341 Section 5 Winter 2018.
String and Lists Dr. José M. Reyes Álamo.
Python Tutorial for C Programmer Boontee Kruatrachue Kritawan Siriboon
Fundamentals of Functional Programming
SE1H421 Procedural Programming LECTURE 4 Operators & Conditionals (1)
Introduction to Functional Programming in Racket
(more) Python.
Lambda Functions, MapReduce and List Comprehensions
Important Concepts from Clojure
Curry A Tasty dish? Haskell Curry!.
Functions Functions being objects means functions can be passed into other functions: sort (list, key=str.upper)
Clojure 3 1-Jun-19.
Rules of evaluation The value of a number is itself.
Chapter 15 Functional Programming 6/1/2019.
Functions John R. Woodward.
Lecture 2 - Names & Functions
Presentation transcript:

Introduction to Higher Order (Functional Programming) (Python) part 2 John R. Woodward

Higher Order Function A higher order function is a function which - take another function as input Or Returns a function as output.

What does the following print foo = [2, 18, 9, 22, 17, 24, 8, 12, 27] print filter(lambda x: x % 3 == 0, foo) print map(lambda x: x * 2 + 10, foo) print reduce(lambda x, y: x + y, foo)

output [18, 9, 24, 12, 27] [14, 46, 28, 54, 44, 58, 26, 34, 64] 139

What does the following print foo = [2, 18, 9, 22, 17, 24, 8, 12, 27] print type(filter(lambda x: x % 3 == 0, foo)) print type(map(lambda x: x * 2 + 10, foo)) print type(reduce(lambda x, y: x + y, foo))

output <type 'list'> <type 'int'>

Lambda – filter, map, reduce foo = [2, 18, 9, 22, 17, 24, 8, 12, 27] print filter(lambda x: x % 3 == 0, foo) #[18, 9, 24, 12, 27] print map(lambda x: x * 2 + 10, foo) #[14, 46, 28, 54, 44, 58, 26, 34, 64] print reduce(lambda x, y: x + y, foo) #139 #(more detail in a few slides)

Lists Functional programming uses LISTs as its primary data structure. E.g. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] listNumbers = [1,2,3] #[1,2,3] listNumbers.append(4)#[1, 2, 3, 4] listNumbers.insert(2, 55)#[1, 2, 55, 3, 4] listNumbers.remove(55)#[1, 2, 3, 4] listNumbers.index(4)#3 listNumbers.count(2)#1

Map – (a transformation) Map takes a function and a list and applies the function to each elements in the list def cube(x): return x*x*x print map(cube, range(1, 11)) print map(lambda x :x*x*x, range(1, 11)) print map(lambda x :x*x*x, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) # [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000] #what is the type signature

filter Filter takes a function (what type???) and a list, and returns items which pass the test def f1(x): return x % 2 != 0 def f2(x): return x % 3 != 0 def f3(x): return x % 2 != 0 and x % 3 != 0 print filter(f1, range(2, 25)) print filter(f2, range(2, 25)) print filter(f3, range(2, 25))

filter 2 def f1(x): return x % 2 != 0 def f2(x): return x % 3 != 0 def f3(x): return x % 2 != 0 and x % 3 != 0 print filter(f1, range(2, 25)) # [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23]#odd print filter(f2, range(2, 25)) # [2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23] #not divisible by 3 print filter(f3, range(2, 25)) # [5, 7, 11, 13, 17, 19, 23]#not divisible by 2 or 3

A list can contain different datatypes list1 = [0, 1, 0.0, 1.0, True, False, "True", "False", "", None, [True], [False]] def isTrue(x): return x print filter(isTrue, list1)

output list1 = [0, 1, 0.0, 1.0, True, False, "True", "False", "", None, [True], [False]] #answer [1, 1.0, True, 'True', 'False', [True], [False]]

Reduce – try this reduce( (lambda x, y: x + y), [1,2,3,4] )

answers reduce( (lambda x, y: x + y), [1, 2, 3, 4] ) 10 -8 24

The last one print reduce( (lambda x, y: x / y), [1.0, 2.0, 3.0, 4.0] ) ??? answer

The last one print reduce( (lambda x, y: x / y), [1.0, 2.0, 3.0, 4.0] ) 0.0416666666667 # what is the type signature?

Map, Reduce, Filter Map, reduce and filter all take a function as an argument. What type is the function in each case Map, Reduce, Filter

Data Types of Function Taken. Map: takes an argument of type T and returns a type S. It returns a list of S, denoted [S] Reduce: takes two arguments of type T, and returns an argument of type T Filter: take an argument of type T and returns a Boolean (True/False). It returns a list of T, denoted [T]

Partial Application Motivating example Addition (+) takes two arguments (arg1 + arg2) What if we only supply one argument? We cannot compute e.g. (1+) But it is still a function of one argument (1+ could be called what???)

Visualization ??? 3 ADD ADD 1 ??? 1 2 This is how we normally think of the add function

Inc as partial add #add (2 args), inc(x)=add(1,x) #inc is a special case of add from functools import partial def add(a,b): return a+b inc = partial(add, 1) print inc(4)

Inc defined with add #add takes 2 arguments def add(x,y): return x+y #we can define a new function by hardcoding one variable def inc(x): return add(1,x) print inc(88)

double as partial mul #mul(2 args), double(x)=mul(2,x) #double is a special case of mul from functools import partial def mul(a,b): return a*b double = partial(mul, 2) print double(10)

Functions as special cases #square and cube are special cases of the power function def power(base, exponent): return base ** exponent def square(base): return power(base, 2) def cube(base): return power(base, 3)

Equivalent Code from functools import partial square = partial(power, exponent=2) cube = partial(power, exponent=3)

referential transparency Haskell is a pure functional language referential transparency - the evaluation of an expression does not depend on context. The value of an expression can be evaluated in any order (all sequences that terminate return the same value) (1+2)+(3+4) we could reduce this in any order. In the 2nd world war, Richard Feynman was in charge of making calculation for the atomic bomb project. These calculations were done by humans working in parallel. e.g. calculate exponential

Functional Programming Programming paradigm? Object oriented, imperative Immutable state (referential transparency) Higher order functions, partial functions, anonymous functions (lambda) Map, filter, reduce (fold) List data structures and recursion feature heavily Type inference (type signatures) Lazy and eager evaluation, list comprehension

State & Referential Transparency In maths, a function depends ONLY ON ITS INPUTS e.g. root(4) = +/-2 This is a “stateless function” A stateful function (method, procedure) stores some data which changes i.e. mutable data E.g. a “function” which returns the last argument it was given F(4) = -1, F(55) = 4, F(3) = 55, F(65) = 55, (side effects, e.g. accessing a file) Harder to debug stateful function than stateless (why).

List Comprehensions List comprehensions provide a concise way to create lists.  To make new lists, where each element is the result of some operation applied to each member of another sequence.

List Comprehensions The following are common ways to describe lists (or sets, or tuples, or vectors) in mathematics. S = {x² : x in 0 ... 9} V = (1, 2, 4, 8, ..., 2¹²) M = {x | x in S and x even}

Create a list of squares For example, assume we want to create a list of squares, like: squares = [] for x in range(10): squares.append(x**2) print squares #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

As a list comprehension We can obtain the same result with: squares = [x**2 for x in range(10)] This is also equivalent to  squares = map(lambda x: x**2, range(10)), However the list comprehension is more concise and readable. (choose the way that works for you, but do try different techniques)

In Python S = [x**2 for x in range(10)] V = [2**i for i in range(13)] M = [x for x in S if x % 2 == 0] print S; print V; print M

In Python S = [x**2 for x in range(10)] V = [2**i for i in range(13)] M = [x for x in S if x % 2 == 0] print S; print V; print M [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] [0, 4, 16, 36, 64]

Calculating Primes We can calculate the primes by first build a list of non-prime numbers, then use another list comprehension to get the "inverse" of the list,

Calculating Primes noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)] print noprimes primes = [x for x in range(2, 50) if x not in noprimes] print primes

output noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)] print noprimes #[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 10, 15, 20, 25, 30, 35, 40, 45, 12, 18, 24, 30, 36, 42, 48, 14, 21, 28, 35, 42, 49] primes = [x for x in range(2, 50) if x not in noprimes] print primes #[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Nested List Comprehensions You can nest list comprehensions (just like you can do with other python commands). In this case just substitute the “noprimes” variable with the python code. I would not recommend this, as it is harder to read It is also harder to debug (where would you insert a print statement)

Nested List Comprehensions primes = [x for x in range(2, 50) if x not in [j for i in range(2, 8) for j in range(i*2, 50, i)]] print primes #[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

List Comprehension with Strings words = 'The quick brown fox jumps over the lazy dog'.split() print words stuff = [[w.upper(), w.lower(), len(w)] for w in words] for i in stuff: print i

List Comprehension with Strings words = 'The quick brown fox jumps over the lazy dog'.split() print words stuff = [[w.upper(), w.lower(), len(w)] for w in words] for i in stuff: print i ['THE', 'the', 3] ['QUICK', 'quick', 5] ['BROWN', 'brown', 5] ['FOX', 'fox', 3] ['JUMPS', 'jumps', 5] ['OVER', 'over', 4] ['LAZY', 'lazy', 4] ['DOG', 'dog', 3]

Output 2 <type 'list'> words = 'The quick brown fox jumps over the lazy dog'.split() stuff = [[w.upper(), w.lower(), len(w)] for w in words] for i in stuff: print i print type(words) print type(stuff) <type 'list'>

3 EXAMPLES print [y for y in [3,1,4]] print [(x, y) for x in [1,2,3] for y in [3,1,4]] print [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y] OUTPUT [3, 1, 4] [(1, 3), (1, 1), (1, 4), (2, 3), (2, 1), (2, 4), (3, 3), (3, 1), (3, 4)] [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Written as nested for loops [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y] Is equivalent to combs = [] for x in [1,2,3]: for y in [3,1,4]: if x != y: combs.append((x, y)) the order of the for and if statements is the same in both (choose the way that works for you, but do try different techniques)

More examples vec = [-4, -2, 0, 2, 4] print [x*2 for x in vec] print [x for x in vec if x >= 0] print [abs(x) for x in vec] fruits = [' banana', ' loganberry ', 'passion fruit '] 4. print [fruit.strip() for fruit in fruits] 5. print [(x, x**2) for x in range(6)]

More examples vec = [-4, -2, 0, 2, 4] print [x*2 for x in vec] print [x for x in vec if x >= 0] print [abs(x) for x in vec]

More examples vec = [-4, -2, 0, 2, 4] print [x*2 for x in vec] print [x for x in vec if x >= 0] print [abs(x) for x in vec] [-8, -4, 0, 4, 8] [0, 2, 4] [4, 2, 0, 2, 4]

More examples fruits = [' banana', ' loganberry ', 'passion fruit '] 4. print [fruit.strip() for fruit in fruits] 5. print [(x, x**2) for x in range(6)]

More examples fruits = [' banana', ' loganberry ', 'passion fruit '] 4. print [fruit.strip() for fruit in fruits] 5. print [(x, x**2) for x in range(6)] ['banana', 'loganberry', 'passion fruit'] [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]

examples matrix = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12],] print [row[i] for row in matrix for i in range(4)] print [[row[i]] for row in matrix for i in range(4)] print [[row[i] for row in matrix] for i in range(4)]

output [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12]] [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

Equivalent to … transposed = [] for i in range(4): # the following 3 lines implement the nested listcomp transposed_row = [] for row in matrix: transposed_row.append(row[i]) transposed.append(transposed_row)