230 likes | 355 Views
COMP313A Functional Programming (1). LISP…. McCarthy’s main contributions were the conditional expression and its use in writing recursive functions. Scheme (define fac (lambda (n) (if (= n 0) 1 (if (> n 0) (* n (fac (- n 1))) 0)))). Scheme
E N D
LISP… • McCarthy’s main contributions were • the conditional expression and its use in writing recursive functions Scheme (define fac (lambda (n) (if (= n 0) 1 (if (> n 0) (* n (fac (- n 1))) 0)))) Scheme (define fac2 (lambda (n) (cond ((= n 0) 1) ((> n 0) (* n (fac2 (- n 1)))) (else 0)))) Haskell fac ::Int -> Int fac n | n == 0 = 1 | n > 0 = fac(n-1) * n | otherwise = 0 Haskell fac :: Int -> Int fac n = if n == 0 then 1 else if n > 0 then fac(n-1) * n else 0
Lisp… 2. the use of lists and higher order operations over lists such as mapcar Scheme (define mymap (lambda (f a b) (cond ((and (null? a) (null? b)) '()) (else (cons (f (first a) (first b)) (mymap f (rest a) (rest b))))))) Haskell mymap :: (Int -> Int-> Int) -> [Int] -> [Int] ->[Int] mymap f [] [] = [] mymap f (x:xs) (y:ys) = f x y : mymap f xs ys add :: Int -> Int -> Int add x y = x + y Scheme (mymap + ’(3 4 6) ’(5 7 8)) Haskell mymap add [3, 4, 6] [5, 7, 8]
Lisp • cons cell and garbage collection of unused cons cells Scheme (cons ’1 ’(3 4 5 7)) (1 3 4 5 7) Haskell cons :: Int -> [Int] -> [Int] cons x xs = x:xs Scheme (define mymap (lambda (f a b) (cond ((and (null? a) (null? b)) '()) (else (cons (f (first a) (first b)) (mymap f (first a) (first b)))))))
Lisp… • use of S-expressions to represent both program and data An expression is an atom or a list But a list can hold anything…
Scheme (cons ’1 ’(3 4 5 7)) (1 3 4 5 7) Scheme (define mymap (lambda (f a b) (cond ((and (null? a) (null? b)) '()) (else (cons (f (first a) (first b)) (mymap f (first a) (first b)))))))
ISWIM • Peter Landin – mid 1960s • If You See What I Mean Landon wrote “…can be looked upon as an attempt to deliver Lisp from its eponymous commitment to lists, its reputation for hand-to-mouth storage allocation, the hardware dependent flavour of its pedagogy, its heavy bracketing, and its compromises with tradition”
Iswim… • Contributions • Infix syntax • let and where clauses, including a notion of simultaneous and mutually recursive definitions • the off side rule based on indentation • layout used to specify beginning and end of definitions • Emphasis on generality • small but expressive core language
let in Scheme • let* - the bindings are performed sequentially (let* ((x 2) (y 3)) (let* ((x 7) (z (+ x y))) Þ ? (* z x))) (let* ((x 2) (y 3)) Þ ? (* x y))
let in Scheme • let - the bindings are performed in parallel, i.e. the initial values are computed before any of the variables are bound (let ((x 2) (y 3)) (let ((x 7) (z (+ x y))) Þ ? (* z x))) (let ((x 2) (y 3)) Þ ? (* x y))
letrec in Scheme • letrec – all the bindings are in effect while their initial values are being computed, allows mutually recursive definitions (letrec ((even? (lambda (n) (if (zero? n) #t (odd? (- n 1))))) (odd? (lambda (n) (if (zero? n) #f (even? (- n 1)))))) (even? 88))
Emacs was/is written in LISP • Very popular in AI research
ML • Gordon et al 1979 • Served as the command language for a proof generating system called LCF • LCF reasoned about recursive functions • Comprised a deductive calculus and an interactive programming language – Meta Language (ML) • Has notion of references much like locations in memory • I/O – side effects • But encourages functional style of programming
ML • Type System • it is strongly and statically typed • uses type inference to determine the type of every expression • allows polymorphic functions • Has user defined ADTs
SASL, KRC, and Miranda add x y = + x y silly_add x y = x add 4 (3 * a) • Used guards • Higher Order Functions • Lazy Evaluation • Currying switch :: Int -> a -> a -> a switch n x y | n > 0 = x | otherwise = y SASL fac n = 1, n = 0 = n * fac (n-1), n>0 multiplyC :: Int -> Int -> Int Versus multiplyUC :: (Int, Int) -> Int Haskell fac n | n ==0 = 1 | n >0 = n * fac(n-1)
SASL, KRC and Miranda • KRC introduced list comprehension • Miranda borrowed strong data typing and user defined ADTs from ML comp_example :: [Int] -> [Int] comp_example ex = [2 * n | n <- ex]
The Move to Haskell • Lots of functional languages in late 1970’s and 1980’s • Tower of Babel • Among these was Hope • strongly typed • polymorphism but explicit type declarations as part of all function definitions • simple module facility • user-defined concrete data types with pattern matching
The Move to Haskell • 1987 – considered lack of common language was hampering the adoption of functional languages • Haskell was born • higher order functions • lazy evaluation • static polymorphic typing • user-defined datatypes • pattern matching • list comprehensions
Haskell… • as well • module facility • well defined I/O system • rich set of primitive data types
Higher Order Functions • Functions as first class values • stored as data structures, passed as arguments, returned as results • Function is the primary abstraction mechanism • increase the use of this abstraction • Higher order functions are the “guts” of functional programming
Higher Order FunctionsComputations over lists • Mapping • add 5 to every element of a list. • add the corresponding elements of 2 lists • Filtering • Selecting the elements with a certain property • Folding • Combine the items in a list in some way
List Comprehension Double all the elements in a list Using primitive recursion doubleAll :: [Int] -> [Int] doubleAll [] = [] doubleAll x:xs = 2 * x : doubleAll xs Using list comprehension doubleAll :: [Int] -> [Int] doubleAll xs :: [ 2 * x | x <- xs ]
Primitive RecursionversusGeneral Recursion sum :: [Int] -> Int sum [] = 0 sum (x:xs) = x + sum xs qsort :: [Int] -> [Int] qsort [] = [] qsort (x : xs) = qsort [ y | y<-xs , y<=x] ++ [x] ++ qsort [ y | y <- xs , y>x]