= 1 • let add x y = x + y;; int -> int -> int = <fun> • let add x = (fun y -> x + y);; int -> int -> int = <fun> • let doStuff f x = (f x) + 1;; ('a -> int) -> 'a -> int = <fun> • Immutability by default • Functions are first class
in a data structure by its reference and you update it. • By the time the function returns a result, the original data structure has been changed. total = 0 for i in range(len(someSeq)): total = total + someSeq[i]
x++) { total = total + x*x; } let rec sumsq n = if n=0 then 0 else sumsq n*n + sumsq(n-1);; let rec sumof f n = if n=0 then 0 else f n + sumop f (n-1);;
-> 1 | 1 -> 1 | n -> fib(n-1) + fib (n-2);; let rec fib’ n = let rec aux n a b = if n <= 0 then a else aux (n-1) (a+b) a in aux n 1 0;; fib 4 aux 4 1 0 aux 1 3 2 aux 2 2 1 aux 3 1 1 aux 0 5 3 8
compile-time • In advanced languages, automatically inferred • Rules as to what pieces can validly fit together • e.g., 1 + “1” does not make sense. • Can build proofs of correctness
Red | Blue | Green;; type ‘a tree = Leaf of ‘a | Node of ‘a tree * ‘a tree;; let r = { num = 3; denom = 4};; let ratio_to_float r = match r with | {num = n; denom = v} -> (float_of_int n) /. (float_of_int v);;
be first-class: • It has a value and type • Passed as arguments • Can be constructed at runtime • Stored inside data structures • More abstraction, more generic program code
-> 0 | y::ys -> y + (sum ys) let rec prod xs = match xs with | [] -> 1 | y::ys -> y * (sum ys) let map f xs = let rec aux xs = match xs with | [] -> [] | y::ys -> (f y)::(aux ys) in aux xs ;;
-> 0 | y::ys -> y + (sum ys) let rec prod xs = match xs with | [] -> 1 | y::ys -> y * (sum ys) let map f xs = let rec aux xs = match xs with | [] -> [] | y::ys -> (f y)::(aux ys) in aux xs ;; map (+) [1;2;3];; map (*) [1;2;3];;
-> 0 | y::ys -> y + (sum ys) let rec prod xs = match xs with | [] -> 1 | y::ys -> y * (sum ys) let map f xs = let rec aux xs = match xs with | [] -> [] | y::ys -> (f y)::(aux ys) in aux xs ;; map (+) [1;2;3];; map (*) [1;2;3];;
-> 0 | y::ys -> y + (sum ys) let rec prod xs = match xs with | [] -> 1 | y::ys -> y * (sum ys) let map f xs = let rec aux xs = match xs with | [] -> [] | y::ys -> (f y)::(aux ys) in aux xs ;; let double xs = map (fun x -> 2*x) xs let is_pos xs = map (fun x -> x>0) xs map (+) [1;2;3];; map (*) [1;2;3];;
-> 0 | y::ys -> y + (sum ys) let rec prod xs = match xs with | [] -> 1 | y::ys -> y * (sum ys) let map f xs = let rec aux xs = match xs with | [] -> [] | y::ys -> (f y)::(aux ys) in aux xs ;; let double xs = map (fun x -> 2*x) xs let is_pos xs = map (fun x -> x>0) xs map (+) [1;2;3];; map (*) [1;2;3];;
match xs with | [] -> [] | y::ys -> if (p y) then y::(aux ys) else aux ys in aux xs let keep_pos xs = filter (fun x -> x>0) [-3;-2;-1;0;1;2];; # int list = [1;2] let smaller n xs = filter (fun x -> String.length x<=n) 3 [“myatnoe”; “ocaml”; “xxxx”];;
the given function over and over. List.fold_left: ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun> List.fold_right- : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b = <fun>
xs product [] = 1 product (x:xs) = x * product xs and [] = True and (x:xs) = x && and xs or [] = False or (x:xs) = x || or xs sum = foldr (+) 0 l product = foldr (*) 1 l and = foldr (&&) True or = foldr (||) False
beneath a lot of functional langauges (e.g., Lisp, Haskell ..) • Caputres core aspects of computation • Turing complete • Discusses a lot of reduction/evaluation strategies, fundamental concepts, currying, church booleans (λx. λy.x, λx. λy.y), function pairs, church numerals, typing .,etc
beneath a lot of functional langauges (e.g., Lisp, Haskell ..) • Caputres core aspects of computation • Turing complete • Discusses a lot of reduction/evaluation strategies, fundamental concepts, currying, church booleans (λx. λy.x, λx. λy.y), function pairs, church numerals, typing .,etc • In its simplest universal form, there is untyped lambda calculus.
call. (Call by value) e.g., C, Java, ML • Non-strict languages will enter function call and only evaluate the arguments as they are required. (Call by name). Lazy languages like Haskell by default will use call-by-need.
data structures only specified imperatively • Culture • JVM problems • Lack of support for full tail call optimization requires more workarounds • funarg problem