TI1220 Lecture 6: First-class Functions

1,462 views
1,349 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,462
On SlideShare
0
From Embeds
0
Number of Embeds
944
Actions
Shares
0
Downloads
20
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

TI1220 Lecture 6: First-class Functions

  1. 1. Lecture 6: First-Class Functions TI1220 2012-2013 Concepts of Programming Languages Eelco Visser / TU Delft
  2. 2. Messages from the Lab
  3. 3. Graded Assignment 1 Algebraic datatypes in C Dynamic dispatch in CImportant dates Deadline: April 2, 2013 23:59 Extension: April 5, 2013 23:59 Submitting after extension date is not possible Maximum penalty for submitting after deadline: 6 points Minimum grade needed: 4 Grade: 70% unit tests, 30% check lists Grade for GAs: average of four assignments
  4. 4. Alonzo Church (June 14, 1903 – August 11, 1995) wasan American mathematician and logician who made majorcontributions to mathematical logic and the foundations oftheoretical computer science. He is best known for thelambda calculus, Church–Turing thesis, proving theundecidability of the Entscheidungsproblem, Frege–Churchontology, and the Church–Rosser theorem.The lambda calculus emerged in his famous 1936 paper showing the unsolvability ofthe Entscheidungsproblem. This result preceded Alan Turings famous work on thehalting problem, which also demonstrated the existence of a problem unsolvable bymechanical means. Church and Turing then showed that the lambda calculus and theTuring machine used in Turings halting problem were equivalent in capabilities, andsubsequently demonstrated a variety of alternative "mechanical processes forcomputation." This resulted in the Church–Turing thesis.The lambda calculus influenced the design of the LISP programming language andfunctional programming languages in general. The Church encoding is named in hishonor. http://en.wikipedia.org/wiki/Alonzo_Church
  5. 5. Outline Lambda calculus First-class functions in JavaScript Functions as objects in Java First-class functions in Scala Generic, higher-order functions Control abstraction
  6. 6. Lambda Calculus
  7. 7. Syntax• Variables: x• Functions: λ x . M Lambda Calculus• Application: (M N)Semantics• Beta reduction: (λ x . M) N ≡ M[x := N]Example• ((λ c . (λ x . c)) 1) 2 ≡ (λ x . 1) 2 ≡ 1
  8. 8. Free Variables Lambda Calculus• fvs(x) ≡ {x}• fvs(λ x . M) ≡ fvs(M) / {x}• fvs(M N) ≡ fvs(M) ∪ fvs(N)Example• fvs(λ c . x (λ x . z c)) ≡ {x, z}
  9. 9. Lambda CalculusSubstitution• x [x := N] ≡ N• y [x := N] ≡ y if x ≢ y• (λ x . M) [x := N] ≡ λ x . M• (λ y . M) [x := N] ≡ λ y . (M [x := N]) if x ≢ y, y ∉ fvs(N)• (M N) [x := P] ≡ (M[x := P])(N[x := P])Example• (λ x . (λ z . x z) (x z)) [z := k] ≡ (λ x . (λ z . x z) (x k))
  10. 10. What is the relevance of the lambda calculus?
  11. 11. Lambda = first-class function Beta reduction = function evaluationLambda calculus = essence of functional programminginstantiated in many modern programming languages
  12. 12. First-order functions• Function definition Functions are Values• Function callFirst-class functions• unnamed function literals (x: Int) => x + 1• pass functions around as values: return as result, pass as parameter, store in data structure
  13. 13. Code reuse• name and parameterize expressions and statementsFunctional abstraction in Java• methodsFunctional abstraction in Scala• nested functions• function literals• function values
  14. 14. First-Class Functions in JavaScript
  15. 15. // Print the name and value of each property of o. Return undefined.function printprops(o) { for ( var p in o) console.log(p + ": " + o[p] + "n");}// Compute the distance between Cartesian points (x1,y1) and (x2,y2).function distance(x1, y1, x2, y2) { var dx = x2 - x1; var dy = y2 - y1; return Math.sqrt(dx * dx + dy * dy);}// A recursive function (one that calls itself) that computes factorials// Recall that x! is the product of x and all positive integers less than it.function factorial(x) { if (x <= 1) return 1; return x * factorial(x - 1);} Named Function Definitions
  16. 16. Anonymous Function Expressions// This function expression defines a function that squares its argument.// Note that we assign it to a variablevar square = function(x) { return x * x;}// Function expressions can include names, which is useful for recursion.var f = function fact(x) { if (x <= 1) return 1; else return x * fact(x - 1);};// Function expressions can also be used as arguments to other functions:data.sort(function(a, b) { return a - b; });// Function expressions are sometimes defined and immediately invoked:var tensquared = (function(x) { return x * x; }(10));
  17. 17. var incrementer = Nested functions: Closures function (base) { return function (x) { return x + base; }; };var inc3 = incrementer(3);inc3(39); remember value of baseincrementer = base . ( x . (x + base))inc3 = incrementer 3;inc3 39 In lambda notation
  18. 18. var scope = "global scope"; // A global variable Closuresfunction checkscope() { var scope = "local scope"; // A local variable function f() { return scope; } // Return the value in scope here return f();}checkscope() // => "local scope" var scope = "global scope"; // A global variable function checkscope() { var scope = "local scope"; // A local variable function f() { return scope; } // Return the value in scope here return f; } checkscope()() // What does this return?
  19. 19. var uniqueInteger = (function() { // Define and invoke var counter = 0; // Private state of function below return function() { return counter++; }; Closures with state}()); function counter() { var n = 0; return { count: function() { return n++; }, reset: function() { n = 0; } }; } var c = counter(), d = counter(); // Create two counters c.count() // => 0 d.count() // => 0: they count independently c.reset() // reset() and count() methods share state c.count() // => 0: because we reset c d.count() // => 1: d was not reset
  20. 20. // This function returns a function that always returns vfunction constfunc(v) { return function() { return v; }; }// Create an array of constant functions:var funcs = [];for(var i = 0; i < 10; i++) funcs[i] = constfunc(i);// The function at array element 5 returns the value 5.funcs[5]() // => 5 Accidental closure state // Return an array of functions that return the values 0-9 function constfuncs() { var funcs = []; for ( var i = 0; i < 10; i++) funcs[i] = function() { return i; }; return funcs; } var funcs = constfuncs(); funcs[5]() // What does this return?
  21. 21. function compose(f, g) { return function() { // We use call for f because were passing a single value // and apply for g because were passing an array of values. return f.call(this, g.apply(this, arguments)); };}var square = function(x) { return x * x; Higher-Order Functions};var sum = function(x, y) { return x + y;};var squareofsum = compose(square, sum);squareofsum(2, 3) // => 25
  22. 22. function incList(xs) { var ys = []; for(i in xs) { ys[i] = xs[i] + 1; } return ys;}incList([1, 2, 3]) // returns [2, 3, 4]function map(f, xs) { Higher-Order Functions var ys = []; for(i in xs) { ys[i] = f(xs[i]); } return ys;}function incList2(xs) { return map(function (x) { return x + 1; }, xs);}incList2([1, 2, 3]) // returns [2, 3, 4]
  23. 23. Functions as Objects in Java
  24. 24. Does Java support first-class functions?
  25. 25. interface IntFun { Int apply(Int x)}class Inc implements IntFun { Int apply(Int x) { return x + 1; }}class Foo { void f(IntFun g) { g.apply(...) }} ... foo.f(new Inc) ... Functions as Objects in Java
  26. 26. First-Class Functions in Scala
  27. 27. Function Literals((c: Int) => ((x: Int) => c+x))(1)(2)evaluation steps:- ((x: Int) => 1+x) (2)- 1+2- 3
  28. 28. scala> var increase = (x: Int) => x + 1 Function Values are Objectsincrease: (Int) => Int = <function1>scala> increase(10)res0: Int = 11scala> increase = (x: Int) => x + 9999increase: (Int) => Int = <function1>scala> increase(10)res1: Int = 10009scala> increase.apply(10)res37: Int = 11 <function>(<args>) abbreviates <function>.apply(<args>)
  29. 29. Generic Higher-Order Functions (in Scala)
  30. 30. Re-occurring patterns• transform every element of a list• verify property of all elements of a list• extract elements satisfying some criterion• combining elements of a list using some operatorHigher-order functions• direct, reusable definitions of such patterns
  31. 31. def inc(xs: IntList): IntList = xs match { case Nil() => Nil() case Cons(y, ys) => Cons(y + 1, inc(ys))}def square(xs: IntList): IntList = xs match { case Nil() => Nil() case Cons(y, ys) => Cons(y * y, square(ys))} Transform each element of a list
  32. 32. Factor out the transformation def map(xs: IntList, f: Int => Int): IntList = xs match { case Nil() => Nil() case Cons(y, ys) => Cons(f(y), map(ys, f)) } def inc(xs: IntList) = map(xs, ((x:Int) => x + 1)) def square(xs: IntList) = map(xs, ((x:Int) => x * x))
  33. 33. Lists in Scala Library val fruit : List[String] = List("apples", "oranges", "pears") val nums: List[Int] = List(1, 2, 3, 4) val diag3: List[List[Int]] = List( List(1, 0, 0), List(0, 1, 0), List(0, 0, 1)) val empty = List()Lists are polymorphic: parameterized with type of elements
  34. 34. Factor out type A => B : type of functions from type A to type B def map[A,B](xs: List[A], f: A => B): List[B] = xs match { case List() => List() case y :: ys => f(y) :: map(ys, f) } val l = map(List(1, 2, 3), ((x: Int) => x + 1)) Polymorphic function: parameterized with types
  35. 35. scala> List(1, 2, 3) map (_ + 1) Map in Scala Libraryres29: List[Int] = List(2, 3, 4)scala> val words = List("the", "quick", "brown", "fox")words: List[java.lang.String] = List(the, quick, brown, fox)scala> words map (_.length)res30: List[Int] = List(3, 5, 5, 3)scala> words map (_.toList.reverse.mkString)res31: List[String] = List(eht, kciuq, nworb, xof)scala> words map (_.toList)res32: List[List[Char]] =List(List(t,h,e), List(q,u,i,c,k), List(b,r,o,w,n), List(f,o,x))scala> words flatMap (_.toList)res33: List[Char] = List(t,h,e,q,u,i,c,k,b,r,o,w,n,f,o,x)
  36. 36. Select Elements in a List def even(xs: IntList): IntList = xs match { case Nil() => Nil() case Cons(y, ys) => if(y % 2 == 0) Cons(y, even(ys)) else even(ys) } def primes(xs: IntList): IntList = xs match { case Nil() => Nil() case Cons(y, ys) => if(isPrime(y)) Cons(y, primes(ys)) else primes(ys) }
  37. 37. def filter(xs: IntList, p: Int => Boolean): IntList =xs match { case Nil() => Nil() case Cons(y, ys) => if(p(y)) Cons(y, filter(ys, p)) else filter(ys, p)}def evenF(xs: IntList) = filter(xs, ((x: Int) => x % 2 == 0))def primes(xs: IntList) = filter(xs, isPrime _) Factor out Predicate
  38. 38. Factor out Type of Elementsdef filter[A](xs: List[A], p: A => Boolean): List[A] = xs match { case List() => List() case y :: ys => if(p(y)) (y :: filter(ys, p)) else filter(ys, p) }def evenF(xs: List[Int]) = filter[Int](xs, ((x: Int) => x % 2 == 0))def primes(xs: List[Int]) = filter[Int](xs, isPrime _)
  39. 39. scala> List(1, 2, 3, 4, 5) filter (_ % 2 == 0)res37: List[Int] = List(2, 4)scala> words filter (_.length == 3)res38: List[java.lang.String] = List(the, fox)scala> List(1, 2, 3, 4, 5) partition (_ % 2 == 0)res39: (List[Int], List[Int]) = (List(2, 4),List(1, 3, 5))scala> List(1, 2, 3, 4, 5) find (_ % 2 == 0)res40: Option[Int] = Some(2)scala> List(1, 2, 3, 4, 5) find (_ <= 0)res41: Option[Int] = None Filtering in Scala Libraryscala> List(1, 2, 3, 4,5) takeWhile (_ > 0)res42: List[Int] = List(1, 2, 3)scala> words dropWhile (_ startsWith "t")res43: List[java.lang.String] = List(quick, brown, fox)scala> List(1, 2, 3, 4,5) span (_ > 0)res44: (List[Int], List[Int]) = (List(1, 2, 3),List(4, 5)) xs partition p equals (xs filter p, xs filter (!p(_)))
  40. 40. def sum(xs: IntList): Int = xs match { case Nil() => 0 case Cons(y, ys) => y + sum(ys)}def product(xs: IntList): Int = xs match { case Nil() => 1 case Cons(y, ys) => y * product(ys)} Combining Elements
  41. 41. Factor out operatordef foldRight(xs: IntList, z: Int, op: (Int,Int)=>Int): Int = xs match { case Nil() => z case Cons(y, ys) => op(y, foldRight(ys, z, op)) }def sum(xs: IntList): Int = foldRight(xs, 0, (x: Int, y: Int) => x + y)def product(xs: IntList): Int = foldRight(xs, 1, (x: Int, y: Int) => x * y)
  42. 42. def foldLeft(xs: IntList, z: Int, op: (Int,Int) => Int): Int = xs match { case Nil() => z case Cons(y, ys) => foldLeft(ys, op(z, y), op) }def sumF(xs: IntList): Int = foldLeft(xs, 0, (x: Int, y: Int) => x + y) Tail recursive folding
  43. 43. Factor out typedef foldLeft[A,B](xs: List[A], z: B, op: (B,A) => B): B = xs match { case List() => z case y :: ys => foldLeft(ys, op(z, y), op) }
  44. 44. scala> ("" /: words) (_ +" "+ _) res46: java.lang.String = the quick brown fox scala> (words.head /: words.tail) (_ +" "+ _) res47: java.lang.String = the quick brown fox(z /: List(a, b, c)) (op)equalsop(op(op(z, a), b), c) Fold left in Scala LibraryList(a, b, c).foldLeft(z)(op)
  45. 45. sum(List(a, b, c)) equals 0 + a + b + cscala> def sum(xs: List[Int]): Int = (0 /: xs) (_ + _)sum: (List[Int])Int Folding Lists product(List(a, b, c)) equals 1 * a * b * c scala> def product(xs: List[Int]): Int = (1 /: xs) (_ * _) sum: (List[Int])Int
  46. 46. Fold Right(List(a, b, c) : z) (op)equalsop(a, op(b, op(c, z))) List(a, b, c).foldRight(z)(op)
  47. 47. Map defined with Fold def map[A,B](xs: List[A], f : A => B): List[B] = (xs : List[B]())( (x: A, ys: List[B]) => f(x) :: ys )Filter defined with Fold def filter[A](xs: List[A], p : A => Boolean): List[A] = (xs : List[A]())( (x: A, ys: List[A]) => if(p(x)) x :: ys else ys )
  48. 48. Re-occurring patterns• transform every element of a list• verify property of all elements of a list• extract elements satisfying some criterion• combining elements of a list using some operatorHigher-order functions• direct, reusable definitions of such patterns
  49. 49. Higher-order functions• reducing code duplication, simplifying client codeCurrying• partial function applicationsWriting new control structures• growing the languageBy-name parameters• lazy evaluation
  50. 50. Reading & Programming in Week 6Reading Sebesta Chapter 15: Functional Programming Languages Java Script TGP Chapter 4: FunctionsWebLab: C, JavaScript, Scala tutorials Graded Assignment 1: Dynamic Dispatch in C (deadline 2 April 2013, 23:59) Week 7: Polymorphism

×