CSCC24 Functional Programming Scheme Part 2

Similar documents
CSC324 Functional Programming Efficiency Issues, Parameter Lists

Functional Programming. Pure Functional Languages

Introduction to Functional Programming in Racket. CS 550 Programming Languages Jeremy Johnson

Functional Languages. Hwansoo Han

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

Functional Programming. Pure Functional Programming

Functional Programming. Pure Functional Languages

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

Functional Programming. Big Picture. Design of Programming Languages

Functional Programming - 2. Higher Order Functions

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

Introduction to Scheme

Racket. CSE341: Programming Languages Lecture 14 Introduction to Racket. Getting started. Racket vs. Scheme. Example.

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

SCHEME The Scheme Interpreter. 2 Primitives COMPUTER SCIENCE 61A. October 29th, 2012

Intro. Scheme Basics. scm> 5 5. scm>

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

LECTURE 16. Functional Programming

Principles of Programming Languages Topic: Functional Programming Professor L. Thorne McCarty Spring 2003

SCHEME AND CALCULATOR 5b

FP Foundations, Scheme

Organization of Programming Languages CS3200/5200N. Lecture 11

CS 314 Principles of Programming Languages

Functional Programming and Haskell

Functional abstraction. What is abstraction? Eating apples. Readings: HtDP, sections Language level: Intermediate Student With Lambda

Functional abstraction

Announcements. The current topic: Scheme. Review: BST functions. Review: Representing trees in Scheme. Reminder: Lab 2 is due on Monday at 10:30 am.

Introduction to Functional Programming in Haskell 1 / 56

Chapter 1. Fundamentals of Higher Order Programming

Fall 2018 Discussion 8: October 24, 2018 Solutions. 1 Introduction. 2 Primitives

Principles of Programming Languages

CS115 - Module 9 - filter, map, and friends

An introduction to Scheme

Functional programming with Common Lisp

Programming Languages Third Edition

CS115 - Module 10 - General Trees

Functional Programming

INTERPRETERS 8. 1 Calculator COMPUTER SCIENCE 61A. November 3, 2016

Scheme Quick Reference

A Small Interpreted Language

Scheme Quick Reference

Scheme Tutorial. Introduction. The Structure of Scheme Programs. Syntax

11/6/17. Functional programming. FP Foundations, Scheme (2) LISP Data Types. LISP Data Types. LISP Data Types. Scheme. LISP: John McCarthy 1958 MIT

Programming Language Pragmatics

Scheme as implemented by Racket

An Introduction to Scheme

Chapter 11 :: Functional Languages

SCHEME 10 COMPUTER SCIENCE 61A. July 26, Warm Up: Conditional Expressions. 1. What does Scheme print? scm> (if (or #t (/ 1 0)) 1 (/ 1 0))

Notes on Higher Order Programming in Scheme. by Alexander Stepanov

6.001 Notes: Section 8.1

CSC 533: Programming Languages. Spring 2015

Basic Scheme February 8, Compound expressions Rules of evaluation Creating procedures by capturing common patterns

CPL 2016, week 10. Clojure functional core. Oleg Batrashev. April 11, Institute of Computer Science, Tartu, Estonia

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Haskell Basics

INF4820: Algorithms for Artificial Intelligence and Natural Language Processing. Common Lisp Fundamentals

A Brief Introduction to Scheme (I)

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

6.001 Notes: Section 6.1

Fundamentals of Artificial Intelligence COMP221: Functional Programming in Scheme (and LISP)

CMSC 330: Organization of Programming Languages. Operational Semantics

MetacircularScheme! (a variant of lisp)

Principles of Programming Languages

Lambda Calculus. Gunnar Gotshalks LC-1

Scheme: Data. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Monday, April 3, Glenn G.

More Scheme CS 331. Quiz. 4. What is the length of the list (()()()())? Which element does (car (cdr (x y z))) extract from the list?

CS 360 Programming Languages Interpreters

Interpreters and Tail Calls Fall 2017 Discussion 8: November 1, 2017 Solutions. 1 Calculator. calc> (+ 2 2) 4

CS 242. Fundamentals. Reading: See last slide

Streams and Evalutation Strategies

CS61A Notes Week 6: Scheme1, Data Directed Programming You Are Scheme and don t let anyone tell you otherwise

CS61A Discussion Notes: Week 11: The Metacircular Evaluator By Greg Krimer, with slight modifications by Phoebus Chen (using notes from Todd Segal)

JVM ByteCode Interpreter

Chapter 15. Functional Programming Languages

User-defined Functions. Conditional Expressions in Scheme

Project 2: Scheme Interpreter

Symbolic Programming. Dr. Zoran Duric () Symbolic Programming 1/ 89 August 28, / 89

Denotational Semantics. Domain Theory

Lists in Lisp and Scheme

CS 61A Interpreters, Tail Calls, Macros, Streams, Iterators. Spring 2019 Guerrilla Section 5: April 20, Interpreters.

Lambda Calculus and Lambda notation in Lisp II. Based on Prof. Gotshalks notes on Lambda Calculus and Chapter 9 in Wilensky.

Scheme. Functional Programming. Lambda Calculus. CSC 4101: Programming Languages 1. Textbook, Sections , 13.7

Contents. Chapter 1 SPECIFYING SYNTAX 1

Homework 1. Notes. What To Turn In. Unix Accounts. Reading. Handout 3 CSCI 334: Spring, 2017

Types and Static Type Checking (Introducing Micro-Haskell)

Lambda Calculus see notes on Lambda Calculus

Introduction to lambda calculus Part 3

Documentation for LISP in BASIC

CONCEPTS OF PROGRAMMING LANGUAGES Solutions for Mid-Term Examination

CS 342 Lecture 7 Syntax Abstraction By: Hridesh Rajan

by the evening of Tuesday, Feb 6

TAIL RECURSION, SCOPE, AND PROJECT 4 11

Programming Languages

Programming with Math and Logic

CPS 506 Comparative Programming Languages. Programming Language Paradigm

G Programming Languages - Fall 2012

Haskell: Lists. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Friday, February 24, Glenn G.

Administrivia. Simple data types

Wellesley College CS251 Programming Languages Spring, 2000 FINAL EXAM REVIEW PROBLEM SOLUTIONS

Chapter 15. Functional Programming Languages

Transcription:

CSCC24 Functional Programming Scheme Part 2 Carolyn MacLeod 1 winter 2012 1 Based on slides from Anya Tafliovich, and with many thanks to Gerald Penn and Prabhakar Ragde. 1

The Spirit of Lisp-like Languages We shall first define a class of symbolic expressions in terms of ordered pairs and lists. Then we shall define five elementary functions and predicates, and build from them by composition, conditional expressions and recursive definitions an extensive class of functions of which we shall give a number of examples. We shall then show how these functions can themselves be expressed as symbolic expressions, and we shall give a universal function apply that allows us to compute from the expressions for a given function its value for given arguments. Finally, we shall define some functions with functions as arguments and give some useful examples. McCarthy, J, [1960]. Recursive functions of symbolic expressions and their computation by machine, Part I. Comm. ACM 3:4; 2

The story so far... We learned a bit about the properties of Scheme and other Lisp dialects (and we will revisit this soon) We talked a bit about lists in scheme They re constructed from pairs, also known as cons pairs, other than the empty list They took advantage of a specific half-register instruction set to efficiently implement linked lists They are the building block of Scheme And, we ve started learning a little about Scheme We re using the pure functional subset - no side effects, denotational semantics, static scoping Data types overview A Scheme expression - it s a value, or we compute its value in a specific way Read - Evaluate - Print loop Finally, we ve talked a bit about recursion and tail recursion 3

Review Questions What does it mean that a functional language has no side effects? Can you explain recursion? How are lists constructed in Scheme? How is Scheme executed? What forms can a Scheme expression have? How is writing a program different in Scheme than in Python? What makes a problem easy to solve with a tail-recursive solution? Could you come up with a grammar for the syntax of Scheme? Can we implement every iterative algorithm recursively? As an aside - you may need to try to solve problems on your own to really understand Scheme and functional programming. Spend a little time working on problems. 4

Recall: In pure functional programming languages, recursion is generally preferred as a matter of style to iterative constructs like while-loops or for-loops. This makes programs easier to prove correct, easier to conceptualize as functions: Try - how do you directly translate a recursive algorithm into an iterative one? An iterative one into a recursive one? What method do you think we use to prove recursive algorithms correct? 5

Structural recursion Structural recusion means we take advantage of a data type s recursive structure to traverse it and perform some operation. (define my-func (lambda (lst) (cond ((empty? lst)... ) (else... (first lst)... (my-func (rest lst))... )))) 6

Linear recursion There is at most one recursive call made in any execution of function body. Useful when repeating an operation n times (Recall n! for example) 7

Tail-recursion The recursive call is in the last function application in function body. Tail-recursion is implemented very efficiently and should be used whenever possible. It is not necessary to save a stack frame if the control flow of the program will never return to that function context. Some problems are naturally tail-recursive. More often, we ll need to use an accumulator or some sort, and a helper function. Recall the tail-recursive version of factorial from last class. 8

Recursion Flat recursion: recursion applied over top items of a list. Deep recursion: (aka tree recursion) recursion applied over all items. Mutual recursion: functions call each other, rather that themselves. 9

Mutual recursion example (define even (lambda (lst) (cond ((empty? lst) empty) (else (cons (first lst) (odd (rest lst))))))) (define odd (lambda (lst) (cond ((empty? lst) empty) (else (even (rest lst)))))) Question - What does this code do? 10

Variable Arity Functions We have declared functions with this syntax: (define <identifier> (lambda (a1 a2...an) <expression>)) That list of arguments can be treated as any other Scheme list, for example: (define <identifier> (lambda lst <expression>) Example - sum of squares version 1 11

Higher-order functions In Python, we have a glimpse of some of the ideas we will be using. Consider the following code snippet: mylist = [1, 2, 3, 4, 5, 6] newlist = [] for item in mylist: newlist = newlist + [item * item] 12

Higher-order functions In Python, we have a glimpse of some of the ideas we will be using. Consider the following code snippet: mylist = [1, 2, 3, 4, 5, 6] newlist = [] for item in mylist: newlist = newlist + [item * item] newlist will be the list [1, 4, 9, 16, 25, 36] 12

Higher-order functions In Python, we have a glimpse of some of the ideas we will be using. Consider the following code snippet: mylist = [1, 2, 3, 4, 5, 6] newlist = [] for item in mylist: newlist = newlist + [item * item] newlist will be the list [1, 4, 9, 16, 25, 36] What does that tell us about for loops in Python? 12

Higher-order functions In Python, we have a glimpse of some of the ideas we will be using. Consider the following code snippet: mylist = [1, 2, 3, 4, 5, 6] newlist = [] for item in mylist: newlist = newlist + [item * item] newlist will be the list [1, 4, 9, 16, 25, 36] What does that tell us about for loops in Python? These loops use an iterator. They iterate in order, through this list. 12

higher order functions But is this necesary? Do we really need to compute these squares one at a time in this order? What if we re doing something far more complicated, and we have a supercomputer or a cluster at our disposal? We can revisit a function you may have met in Python to illustrate, map, and we ll use the python lambda function mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] squares = map(lambda item: item*item, mylist) Question - Does the Python map function still iterate over the items one at a time? If an iterative implementation of map was replaced by a parallel one with arbitrary order of execution, would it matter? 13

higher order functions Python, C and Java have other constructs that use higher order functions, directly or indirectly. For example: Template classes Function pointers List constructors 14

higher order functions We ll move into how this works in Scheme, and look at how this gives us a model for breaking down problems into parallelizable chunks. But first we can step back and look at the concept in general. 15

higher-order functions A higher order function takes a function (or functions) as input values. Consider the similarity between these functions: ;; (all-odd lst) return #t if every element of lst is odd ;; Pre: lst is a list of numbers (define all-odd (lambda (lst) (if (empty? lst) #t (and (odd? (first lst)) (all-odd (rest lst)))))) ;; (all-even lst) return #t if every elt of lst is even ;; Pre: lst is a list of numbers (define all-even (lambda (lst) (if (empty? lst) #t (and (even? (first lst)) (all-even (rest lst)))))) 16

higher-order functions We can use a function as an values, and make a general testing function: ;; (all-test test lst) return #t if test is true of ;; every element of lst ;; Pre: lst is a list ;; test is a predicate procedure applicable to ;; every element of lst (define all-test (lambda (test lst) (if (empty? lst) #t (and (test (first lst)) (all-test (rest lst)))))) 17

higher-order functions Functions can also be the return value of another function: ;; (make-proc f g) return a composition f o g ( or g(f(x)) ;; Pre: the composition f o g is well-defined What would (make-proc + square) return? How would you implement this? 18

higher-order functions: map We can use the Scheme function map like we did the Python map function: take two arguments: a function and a list. build a new list whose elements are the result of applying the function to each element of the (old) list. (define mylist (1 2 3 4 5 6)) (map (lambda (item) (* item item)) mylist) > (1 4 9 16 25 36) The built-in map is more general and more powerful. 19

(map proc l1 l2... higher-order functions: map ln) proc : an n-ary procedure l1 l2... ln : lists of length m apply proc element-wise to elements of l1 l2... ln return the list of results (e1 e2... em) the order of evaluation is unspecified: appears to be evaluated in parallel 20

(map proc l1 l2... higher-order functions: map ln) (map abs (-1 2-3 4 5) ==> (1 2 3 4 5) (map max (1 2 3) (0 5 42)) ==> (1 5 42) (map + (1 2 3) (2 3 4) (3 4 5)) ==> (6 9 12) (map cons (a b c) ((a a) (b b) (c c))) ==> ((a a a) (b b b) (c c c)) (map (lambda (x) (+ x 1)) (1 2 3)) ==> (2 3 4) (map (lambda (x y) (+ 1 (- y x))) (0 5 10) (1 5 11)) ==> (2 1 2) 21

Scheme review Before we continue, let s review the syntax and semantics of Scheme that we ve learned so far: Scheme is made up of expressions, which can be build up according to out grammar. <Expr> ::= <Value> They can be made of different data types: Lists - constructed from pairs, sometimes known as cons pairs. Numbers - multiple numeric types in a heirarchy Symbols - Letters or identifiers. Functions - a first class kind of value in Scheme 22

Scheme review Expressions can also be of other forms: <expr> ::= <function call> <lambda expression> <conditional> <definition> <let macro> (Note: This is not quite a formal grammar of Scheme - why?) 23

Function calls Scheme review <function call> ::= ( < Function ID> {<Argument>}+) 24

Lamda expression Scheme review <lambda expression> ::= ( lambda <Arg List> <expr> ) 25

Conditional Scheme review <conditional> ::= ( cond (<bool expr> <expr>) (<bool expr> <expr>)... (else <expr>)) 26

Definition Scheme review <definition> ::= (define <ID> <Expr>) 27

Let statements - syntactic sugar We re missing one useful Scheme construct from this list - the let expressions. These are syntactic sugar - they can be changed to a different form without evaluation. However, they can make your code clearer, and you should use them where applicable. 28

versions of let (let ([var1 expr1]... [varn exprn]) body) Create local variables and bind them to expression results. The scope of these variables is the body of the let statement. Evaluation: expr1,..., exprn are evaluated in some undefined order, saved, and then assigned to var1,..., varn. In our interpreter, they have the appearance of being evaluated in parallel. 29

Consider: versions of let (define sq-cube (lambda (x) (let ([sqr (* x x)] [cube (* x (* x x))]) (list sqr cube)))) Want to reuse sqr. 30

Want to reuse sqr. versions of let (define sq-cube (lambda (x) (let ([sqr (* x x)] [cube (* x sqr)]) (list sqr cube)))) But this does not work - why? 31

versions of let (let* ([var1 expr1]... [varn exprn]) body) The scope of each variable is the part of the let*-expression to the right of the binding. Evaluation: expr1,..., exprn are evaluated sequentially, from left to right. 32

Use let*: versions of let (define sq-cube (lambda (x) (let* ([sqr (* x x)] [cube (* x sqr)]) (list sqr cube)))) 33

versions of let (letrec ([var1 expr1]... [varn exprn]) body ) Scope: Each binding of a variable has the entire letrec expression as its region. Evaluation: expr1,..., exprn are evaluated in an undefined order, saved, and then assigned to var1,..., varn, with the appearance of being evaluated in parallel. 34

versions of let ;; (length lst) returns the length of lst ;; Pre: lst is a list (define length (lambda (lst) (letrec ([length-tail (lambda (lst len) (if (empty? lst) len (length-tail (rest lst) (+ len 1))))]) (length-tail lst 0)))) 35

(let ([x 2]) (* x x)) versions of let (let ([x 4]) (let ([y (+ x 2)]) (* x y))) (let ([x 4] [y (+ x 2)]) (* x y)) (let* ([x 4] [y (+ x 2)]) (* x y)) 36

(let ([x 2]) (* x x)) 4 versions of let (let ([x 4]) (let ([y (+ x 2)]) (* x y))) 24 (let ([x 4] [y (+ x 2)]) (* x y)) is an error: unbound variable x (let* ([x 4] [y (+ x 2)]) (* x y)) 24 37

versions of let (let ((v1 e1)...(vn en)) expr) ((lambda (v1...vn) expr) e1...en) AND (let* ((v1 e1) (v2 e2)) expr) ((lambda (v1) ((lambda (v2) expr) e2)) e1) All binding of values to variables is by parameter passing ( lambda reduction): no assignment 38

higher-order functions: apply (apply op lst) op : an n-ary procedure lst : list of n arguments to op apply op to elements of lst return result of evaluation 39

(apply op lst) higher-order functions: apply (apply + (1 2 3 4)) (+ 1 2 3 4) 10 (apply cons (a (b c))) (cons a (b c)) (a b c) (apply list (1 2 3 4)) (list 1 2 3 4) (1 2 3 4) (apply cons (a (b c) (d))) (cons a (b c) (d)) Error 40

higher-order functions: fold (foldr op id lst) op : an binary procedure lst : list of arguments apply op right-associatively to elements of lst return result of evaluation the identity element id is always used That is: (foldr op id ()) id (foldr op id (e)) (op e id) (foldr op id (e1 e2... en)) (op e1 (op e2 (op... (op en id)))) 41

higher-order functions: foldr Let s implement a version, myfoldr 42

higher-order functions: foldr (foldr list () (1 2 3 4)) (1 (2 (3 (4 ())))) (myfoldr list () (1 2 3 4)) (list 1 (myfoldr list () (2 3 4))) (list 1 (list 2 (myfoldr list () (3 4)))) (list 1 (list 2 (list 3 (myfoldr list () (4))))) (list 1 (list 2 (list 3 (list 4 (myfoldr list () ()))))) (list 1 (list 2 (list 3 (list 4 ())))) (list 1 (list 2 (list 3 (4 ())))) (list 1 (list 2 (3 (4 ())))) (list 1 (2 (3 (4 ())))) (1 (2 (3 (4 ())))) 43

(foldr op id lst) op cons id () higher-order functions: foldr (1 2 3 4) => (cons 1 (cons 2 (cons 3 (cons 4 ())))) ( + 1 ( + 2 ( + 3 ( + 4 0 )))) => (foldr + 0 (1 2 3 4) (list 1 (list 2 (list 3 (list 4 ())))) => (foldr list () (1 2 3 4) 44

higher-order functions: foldl (foldl op id lst) op : an binary procedure lst : list of arguments apply op left-associatively to elements of lst return result of evaluation the identity element id is always used That is: (foldl op id ()) id (foldl op id (e)) (op id e) (foldl op id (e1 e2... en)) (op... (op (op id e1) e2)...) en ) 45

higher-order functions: foldl (foldl op id lst) In other implementations: (foldl op id ()) id (foldl op id (e)) (op id e) (foldl op id (e1 e2... en)) (op en (op en-1 (op... (op e1 id)))) 46

(foldr op id lst) op cons id () higher-order functions: foldr (define (append list1 list2) (define (map p lst) 47

higher-order functions: foldr (append (1 2 3 4) (5 6 7)) => (foldr cons (5 6 7) (1 2 3 4)) => (cons 1 (foldr cons (5 6 7) (2 3 4))) => (cons 1 (cons 2 (foldr cons (5 6 7) (3 4)))) => (cons 1 (cons 2 (cons 3 (foldr cons (5 6 7) (4))))) => (cons 1 (cons 2 (cons 3 (cons 4 (foldr cons (5 6 7) ()))))) <= (cons 1 (cons 2 (cons 3 (cons 4 (5 6 7))))) = (cons 1 (cons 2 (cons 3 (4 5 6 7)))) = (cons 1 (cons 2 (3 4 5 6 7))) = (cons 1 (2 3 4 5 6 7)) = (1 2 3 4 5 6 7) 48

higher-order functions: foldr (map abs (-1 2-3)) => (foldr (lambda (x r) (cons (abs x) r)) () (-1 2-3)) => ((lambda (x r) (cons (abs x) r)) -1 (foldr (lambda (x r) (cons (abs x) r)) () (2-3))) => ((lambda (x r) (cons (abs x) r)) -1 ((lambda (x r) (cons (abs x) r)) 2 (foldr (lambda (x r) (cons (abs x) r)) () (-3)))) 49

higher-order functions: foldr => ((lambda (x r) (cons (abs x) r)) -1 ((lambda (x r) (cons (abs x) r)) 2 ((lambda (x r) (cons (abs x) r)) -3 (foldr (lambda (x r) (cons (abs x) r)) () ())))) <= ((lambda (x r) (cons (abs x) r)) -1 ((lambda (x r) (cons (abs x) r)) 2 ((lambda (x r) (cons (abs x) r)) -3 ()))) 50

higher-order functions: foldr = ((lambda (x r) (cons (abs x) r)) -1 ((lambda (x r) (cons (abs x) r)) 2 (cons (abs -3) ()))) = ((lambda (x r) (cons (abs x) r)) -1 ((lambda (x r) (cons (abs x) r)) 2 (3))) = ((lambda (x r) (cons (abs x) r)) -1 (cons (abs 2) (3))) = ((lambda (x r) (cons (abs x) r)) -1 (2 3)) = (cons (abs -1) (2 3)) = (1 2 3) 51

Scheme Review We now know all the syntax we will need in Scheme, and we can summarize the functions we know. Everything else can be implemented from this basic set of functions - indeed, we don t even need all of these. Number related functions: =, +, -, *, number? List and symbol related functions: list?, empty?, first, rest, cons, append, list, eq? Higher order functions map, foldr, foldl, fold, apply Other quote/, eval 52

Review Questions How does the Scheme or Python map function differ from a Python for item in list: loop? How are functions values in Scheme? Why should we use tail recursion when possible? Create an ambiguous grammar for code comments /* delimited like so */, then create an unambiguous one. What does it mean that Scheme has no side-effects? Create a tail-recursive function to compute the nth number the fibonacci series. What is the difference between syntax and semantics? What is the difference between denotational and operational semantics? Can you implement append with just the cons function? 53

Consider: FP and Formal Proofs if op is commutative, then (foldr op id lst) = (foldl op id lst) for all op, id, lst. is it true? how would one prove it? 54

FP and Formal Proofs (define len (lambda (lst) (if (empty? lst)) 0 (+ 1 (len (rest lst))))) and (define append (lambda (lst1 lst2) (if (empty? lst1)) lst2 (cons (first lst1) (append (rest lst1) lst2)))) Prove: for all lists l1, l2 (len (append l1 l2)) = (+ (len l1) (len l2)) 55

FP and Formal Proofs Need to establish some axioms / facts first: If lst is a list then 1. lst = (), or 2. exist element X and list Y, s.t. lst = (cons X Y) 56

FP and Formal Proofs Need to establish some axioms / facts first: 0. (define len 1. (lambda (lst) 2. (if (empty? lst)) 3. 0 4. (+ 1 (len (rest lst))))) [1] (len ()) = 0 [lines 2,3] [2] (len (cons X Y)) = (+ 1 (len Y)) [lines 2,4] 57

FP and Formal Proofs Need to establish some axioms / facts first: 0. (define append 1. (lambda (lst1 lst2) 2. (if (empty? lst1)) 3. lst2 4. (cons (first lst1) 5. (append (rest lst1) lst2)))) [3] (append () l2) = l2 [lines 2,3] [4] (append (cons X Y) l2) = (cons X (append Y l2)) [lines 2-5] 58

FP and Formal Proofs Now, given that If lst is a list then 1. lst = (), or 2. exist element X and list Y, s.t. lst = (cons X Y) and the following four facts: [1] (len ()) = 0 [2] (len (cons X Y)) = (+ 1 (len Y)) [3] (append () l2) = l2 [4] (append (cons X Y) l2) = (cons X (append Y l2)) and assuming + performs correct addition, prove: for all lists l1, l2 (len (append l1 l2)) = (+ (len l1) (len l2)) 59

Recursion Induction prove: for all lists l1, l2 (len (append l1 l2)) = (+ (len l1) (len l2)) Proof by structural induction on the list l1. Case: [l1 is ()] (len (append l1 l2)) = (len (append () l2)) [case] = (len l2) [3] = (+ 0 (len l2)) [arith] = (+ (len ()) (len l2)) [1] = (+ (len l1) (len l2)) [case] 60

Recursion Induction prove: for all lists l1, l2 (len (append l1 l2)) = (+ (len l1) (len l2)) Case: [l1 = (cons X Y)] IH: Assume (len (append Y l2)) = (+ (len Y) (len l2)) (len (append l1 l2)) = (len (append (cons X Y) l2)) [case] = (len (cons X (append Y l2))) [4] = (+ 1 (len (append Y l2))) [2] = (+ 1 (+ (len Y) (len l2))) [IH] = (+ (+ 1 (len Y)) (len l2)) [arith] = (+ (len (cons X Y)) (len l2)) [2] = (+ (len l1) (len l2)) [case] 61

parameter lists bind a formal parameter to a list of actual parameters (define list-args (lambda varparam varparam)) (list-args) ==> () (list-args a) ==> (a) (list-args a b c d) ==> (a b c d) 62

parameter lists bind a formal parameter to a list of actual parameters (define rev-args (lambda varparam (reverse varparam))) (rev-args ) ==> () (rev-args a b c) ==> (c b a) (rev-args 5 4 3 2 1) ==> (1 2 3 4 5) 63

parameter lists bind a formal parameter to a list of actual parameters (define sum-non1-args (lambda (fst. varparam) (apply + varparam))) (sum-non1-args 1) ==> 0 (sum-non1-args 1 2) ==> 2 (sum-non1-args 1 2 3) ==> 5 (sum-non1-args ) ==> Error: requires at least 1 argument 64

parameter lists bind a formal parameter to a list of actual parameters (define sum-non12-args (lambda (fst sec. varparam) (apply + varparam))) (sum-non12-args 1 2) ==> 0 (sum-non12-args 1 2 3 4) ==> 7 (sum-non12-args 1) ==> Error: requires at least 2 arguments 65

pure functional languages Programs are viewed as collections of functions. Execution of programs is viewed as evaluation. 66

pure functional languages Referential transparency: The value of a function application is independent of the context in which it occurs. A language is referentially transparent if we may replace one expression with another of equal value anywhere in a program without changing the meaning of the program. Value of f(a,b,c) depends only on the values of f, a, b and c. It does not depend on the global state of computation. 67

pure functional languages Referential transparency: Main advantage: facilitates reasoning about programs and applying program transformations. Aside: Referential transparency is no longer considered a distinguishing feature of functional programming languages. It arguably holds in well-designed imperative languages too. See Mitchell, page 78 for further discussion. 68

pure functional languages Manifest Interface Principle: All interfaces are apparent in syntax. Code is then more modular, arguments are interface(s). 69

pure functional languages No assignment statement: A variable may not have a value, or its value might be a function that has not been applied to its arguments yet, but variables in pure FP are said to be logical in that, having acquired a value in the course of an evaluation, they retain that value until the end of evaluation. This is similar to the manner in which variables are used in mathematics. Remember when you had to unlearn your mathematics training to make sense of x := x+1? In FP, this is anathema! 70

No side effects: pure functional languages Function calls have no side effects. No need to consider global state. Programs are easier to reason about. Programs are easier to prove correct. Historically, imperative programming had to refer to Turing machines to talk about state, however there are very good techniques now. 71

pure functional languages Functions are first-class values: Can be returned as the value of an expression. Can be passed as an argument. Can be put in a data structure as a value. Unnamed functions exist as values. 72

recursion vs. iteration: pure functional languages In pure FP, recursion is generally preferred as a matter of style to iterative constructs like while-loops or for-loops. This makes programs easier to prove correct, easier to conceptualize as functions: Recursions, like functions, identify the structure of one or more arguments as the only values upon which the computation (and termination) depends. 73

a higher-level language: pure functional languages All storage management is implicit: we don t have to think about how program state maps to a computer s memory (or at least, not until we want to write super-efficient code). That means no assignment, no new/free calls to manage our own memory, and no pointers. The state of a computation is much easier to think about. 74