Top Banner
TI1220 2012-2013 Concepts of Programming Languages Eelco Visser / TU Delft Lecture 6: First-Class Functions
51

TI1220 Lecture 6: First-class Functions

May 10, 2015

Download

Documents

Eelco Visser
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: TI1220 Lecture 6: First-class Functions

TI1220 2012-2013Concepts of Programming Languages

Eelco Visser / TU Delft

Lecture 6: First-Class Functions

Page 2: TI1220 Lecture 6: First-class Functions
Page 3: TI1220 Lecture 6: First-class Functions

Messages from the Lab

Page 4: TI1220 Lecture 6: First-class Functions

Graded Assignment 1Algebraic datatypes in CDynamic dispatch in C

Important datesDeadline: April 2, 2013 23:59Extension: April 5, 2013 23:59

Submitting after extension date is not possibleMaximum penalty for submitting after deadline: 6 pointsMinimum grade needed: 4Grade: 70% unit tests, 30% check listsGrade for GAs: average of four assignments

Page 5: TI1220 Lecture 6: First-class Functions

Alonzo Church (June 14, 1903 – August 11, 1995) was an American mathematician and logician who made major contributions to mathematical logic and the foundations of theoretical computer science. He is best known for the lambda calculus, Church–Turing thesis, proving the undecidability of the Entscheidungsproblem, Frege–Church ontology, and the Church–Rosser theorem.

The lambda calculus emerged in his famous 1936 paper showing the unsolvability of the Entscheidungsproblem. This result preceded Alan Turing's famous work on the halting problem, which also demonstrated the existence of a problem unsolvable by mechanical means. Church and Turing then showed that the lambda calculus and the Turing machine used in Turing's halting problem were equivalent in capabilities, and subsequently demonstrated a variety of alternative "mechanical processes for computation." This resulted in the Church–Turing thesis.

The lambda calculus influenced the design of the LISP programming language and functional programming languages in general. The Church encoding is named in his honor.

http://en.wikipedia.org/wiki/Alonzo_Church

Page 6: TI1220 Lecture 6: First-class Functions

Outline

Lambda calculus

First-class functions in JavaScript

Functions as objects in Java

First-class functions in Scala

Generic, higher-order functions

Control abstraction

Page 7: TI1220 Lecture 6: First-class Functions

Lambda Calculus

Page 8: TI1220 Lecture 6: First-class Functions

Syntax

• Variables: x

• Functions: λ x . M

• Application: (M N)

Semantics

• Beta reduction: (λ x . M) N ≡ M[x := N]

Example

• ((λ c . (λ x . c)) 1) 2 ≡ (λ x . 1) 2 ≡ 1

Lambda Calculus

Page 9: TI1220 Lecture 6: First-class Functions

Free Variables

• 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}

Lambda Calculus

Page 10: TI1220 Lecture 6: First-class Functions

Substitution

• 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))

Lambda Calculus

Page 11: TI1220 Lecture 6: First-class Functions

What is the relevance of the lambda calculus?

Page 12: TI1220 Lecture 6: First-class Functions

Lambda = first-class function

Beta reduction = function evaluation

Lambda calculus = essence of functional programming

instantiated in many modern programming languages

Page 13: TI1220 Lecture 6: First-class Functions

First-order functions

• Function definition

• Function call

First-class functions

• unnamed function literals

(x: Int) => x + 1

• pass functions around as values: return as result, pass as parameter, store in data structure

Functions are Values

Page 14: TI1220 Lecture 6: First-class Functions

Code reuse

• name and parameterize expressions and statements

Functional abstraction in Java

• methods

Functional abstraction in Scala

• nested functions

• function literals

• function values

Page 15: TI1220 Lecture 6: First-class Functions

First-Class Functionsin JavaScript

Page 16: TI1220 Lecture 6: First-class Functions

// 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

Page 17: TI1220 Lecture 6: First-class Functions

// 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));

Anonymous Function Expressions

Page 18: TI1220 Lecture 6: First-class Functions

var incrementer = function (base) { return function (x) { return x + base; }; };

var inc3 = incrementer(3);

inc3(39);

incrementer = \ base . ( \ x . (x + base))inc3 = incrementer 3;inc3 39

Nested functions: Closures

In lambda notation

remember value of base

Page 19: TI1220 Lecture 6: First-class Functions

var scope = "global scope"; // A global variablefunction 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 variablefunction 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?

Closures

Page 20: TI1220 Lecture 6: First-class Functions

var uniqueInteger = (function() { // Define and invoke var counter = 0; // Private state of function below return function() { return counter++; };}());

function counter() { var n = 0; return { count: function() { return n++; }, reset: function() { n = 0; } };}var c = counter(), d = counter(); // Create two countersc.count() // => 0d.count() // => 0: they count independentlyc.reset() // reset() and count() methods share statec.count() // => 0: because we reset cd.count() // => 1: d was not reset

Closures with state

Page 21: TI1220 Lecture 6: First-class Functions

// 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

// Return an array of functions that return the values 0-9function 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?

Accidental closure state

Page 22: TI1220 Lecture 6: First-class Functions

function compose(f, g) { return function() { // We use call for f because we're passing a single value // and apply for g because we're passing an array of values. return f.call(this, g.apply(this, arguments)); };}

var square = function(x) { return x * x;};

var sum = function(x, y) { return x + y;};

var squareofsum = compose(square, sum);

squareofsum(2, 3) // => 25

Higher-Order Functions

Page 23: TI1220 Lecture 6: First-class Functions

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) { 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]

Higher-Order Functions

Page 24: TI1220 Lecture 6: First-class Functions

Functions as Objects in Java

Page 25: TI1220 Lecture 6: First-class Functions

Does Java support first-class functions?

Page 26: TI1220 Lecture 6: First-class Functions

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

Page 27: TI1220 Lecture 6: First-class Functions

First-Class Functionsin Scala

Page 28: TI1220 Lecture 6: First-class Functions

((c: Int) => ((x: Int) => c+x))(1)(2)

evaluation steps:

- ((x: Int) => 1+x) (2)

- 1+2

- 3

Function Literals

Page 29: TI1220 Lecture 6: First-class Functions

scala> var increase = (x: Int) => x + 1increase: (Int) => Int = <function1>

scala> increase(10)res0: Int = 11

scala> increase = (x: Int) => x + 9999increase: (Int) => Int = <function1>

scala> increase(10)res1: Int = 10009

scala> increase.apply(10) res37: Int = 11

Function Values are Objects

<function>(<args>) abbreviates

<function>.apply(<args>)

Page 30: TI1220 Lecture 6: First-class Functions

Generic Higher-Order Functions (in Scala)

Page 31: TI1220 Lecture 6: First-class Functions

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 operator

Higher-order functions

• direct, reusable definitions of such patterns

Page 32: TI1220 Lecture 6: First-class Functions

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

Page 33: TI1220 Lecture 6: First-class Functions

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))

Factor out the transformation

Page 34: TI1220 Lecture 6: First-class Functions

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 in Scala Library

Lists are polymorphic: parameterized with type of elements

Page 35: TI1220 Lecture 6: First-class Functions

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))

Factor out type

Polymorphic function: parameterized with types

A => B : type of functions from type A to type B

Page 36: TI1220 Lecture 6: First-class Functions

scala> List(1, 2, 3) map (_ + 1)res29: 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)

Map in Scala Library

Page 37: TI1220 Lecture 6: First-class Functions

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)}

Select Elements in a List

Page 38: TI1220 Lecture 6: First-class Functions

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

Page 39: TI1220 Lecture 6: First-class Functions

def 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 _)

Factor out Type of Elements

Page 40: TI1220 Lecture 6: First-class Functions

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

scala> 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(_)))

Filtering in Scala Library

Page 41: TI1220 Lecture 6: First-class Functions

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

Page 42: TI1220 Lecture 6: First-class Functions

def 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)

Factor out operator

Page 43: TI1220 Lecture 6: First-class Functions

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

Page 44: TI1220 Lecture 6: First-class Functions

def 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) }

Factor out type

Page 45: TI1220 Lecture 6: First-class Functions

(z /: List(a, b, c)) (op)

equals

op(op(op(z, a), b), c)

scala> ("" /: words) (_ +" "+ _)res46: java.lang.String = the quick brown fox

scala> (words.head /: words.tail) (_ +" "+ _)res47: java.lang.String = the quick brown fox

List(a, b, c).foldLeft(z)(op)

Fold left in Scala Library

Page 46: TI1220 Lecture 6: First-class Functions

scala> def sum(xs: List[Int]): Int = (0 /: xs) (_ + _)sum: (List[Int])Int

sum(List(a, b, c)) equals 0 + a + b + c

scala> def product(xs: List[Int]): Int = (1 /: xs) (_ * _)sum: (List[Int])Int

product(List(a, b, c)) equals 1 * a * b * c

Folding Lists

Page 47: TI1220 Lecture 6: First-class Functions

(List(a, b, c) :\ z) (op)

equals

op(a, op(b, op(c, z)))

List(a, b, c).foldRight(z)(op)

Fold Right

Page 48: TI1220 Lecture 6: First-class Functions

def map[A,B](xs: List[A], f : A => B): List[B] = (xs :\ List[B]())( (x: A, ys: List[B]) => f(x) :: ys )

Map 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 )

Filter defined with Fold

Page 49: TI1220 Lecture 6: First-class Functions

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 operator

Higher-order functions

• direct, reusable definitions of such patterns

Page 50: TI1220 Lecture 6: First-class Functions

Higher-order functions

• reducing code duplication, simplifying client code

Currying

• partial function applications

Writing new control structures

• growing the language

By-name parameters

• lazy evaluation

Page 51: TI1220 Lecture 6: First-class Functions

Reading & Programming in Week 6

Reading

Sebesta Chapter 15: Functional Programming Languages

Java Script TGP Chapter 4: Functions

Week 7: Polymorphism

WebLab: C, JavaScript, Scala tutorialsGraded Assignment 1: Dynamic Dispatch in C (deadline 2 April 2013, 23:59)