CMSC 330: Organization of Programming Languages. Closures (Implementing Higher Order Functions)

Similar documents
CMSC 330: Organization of Programming Languages. Closures (Implementing Higher Order Functions)

Anonymous Functions CMSC 330: Organization of Programming Languages

Tuples. CMSC 330: Organization of Programming Languages. Examples With Tuples. Another Example

CMSC 631. Functional Programming with OCaml

CMSC 330: Organization of Programming Languages. OCaml Higher Order Functions

CMSC 330: Organization of Programming Languages. OCaml Higher Order Functions

CMSC 330: Organization of Programming Languages. OCaml Higher Order Functions

COMP 150-AVS Fall OCaml and Functional Programming

CMSC 330: Organization of Programming Languages. Lets, Tuples, Records

Topics Covered Thus Far CMSC 330: Organization of Programming Languages

CMSC 330: Organization of Programming Languages

CMSC330 Fall 2013 Practice Problems 6 Solutions

CMSC 330, Fall 2013, Practice Problem 3 Solutions

Background. CMSC 330: Organization of Programming Languages. Useful Information on OCaml language. Dialects of ML. ML (Meta Language) Standard ML

Tail Calls. CMSC 330: Organization of Programming Languages. Tail Recursion. Tail Recursion (cont d) Names and Binding. Tail Recursion (cont d)

CMSC 330: Organization of Programming Languages. OCaml Expressions and Functions

Topics Covered Thus Far. CMSC 330: Organization of Programming Languages. Language Features Covered Thus Far. Programming Languages Revisited

OCaml Language Choices CMSC 330: Organization of Programming Languages

Closures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming

Dialects of ML. CMSC 330: Organization of Programming Languages. Dialects of ML (cont.) Features of ML. Functional Languages. Features of ML (cont.

CMSC 330, Fall 2013, Practice Problems 3

Every language has its own scoping rules. For example, what is the scope of variable j in this Java program?

CMSC 330: Organization of Programming Languages. Lambda Calculus

CMSC330. Objects, Functional Programming, and lambda calculus

Closures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming

Weeks 6&7: Procedures and Parameter Passing

CMSC 330: Organization of Programming Languages. Lambda Calculus

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

CMSC330 Spring 2015 Final Exam 9:30am/11:00am/12:30pm

CMSC 330: Organization of Programming Languages

Introduction to OCaml

CMSC 330: Organization of Programming Languages. Objects and Functional Programming

Lecture 16: Static Semantics Overview 1

Functional Languages. CSE 307 Principles of Programming Languages Stony Brook University

CSE 341 Section 5. Winter 2018

CMSC330 Fall 2010 Final Exam Solutions

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

CMSC 430 Introduction to Compilers. Fall Everything (else) you always wanted to know about OCaml (but were afraid to ask)

CS Programming Languages: Scala

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Contents. 8-1 Copyright (c) N. Afshartous

Names, Bindings, Scopes

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

INDEX. A SIMPLE JAVA PROGRAM Class Declaration The Main Line. The Line Contains Three Keywords The Output Line

SNU Programming Language Theory

CS 330 Lecture 18. Symbol table. C scope rules. Declarations. Chapter 5 Louden Outline

CS558 Programming Languages. Winter 2013 Lecture 3

An introduction to C++ template programming

CMSC330 Spring 2015 Final Exam 9:30am/11:00am/12:30pm

Parametric types. map: ( a (a b) a list b list. filter: ( a bool) a list a list. Why? a and b are type variables!

CSCE 314 Programming Languages. Type System

Principles of Programming Languages

Concepts Introduced in Chapter 7

OCaml. ML Flow. Complex types: Lists. Complex types: Lists. The PL for the discerning hacker. All elements must have same type.

Monday Feb 16, 5pm. solve these equalities. Midterm Thursday Feb 12. covers only ocaml part of the course, assignments 1 through 3.

Object-oriented programming. and data-structures CS/ENGRD 2110 SUMMER 2018

Functions - Lecture 7. Nested functions. Another example. A Nested Function. Josef Svenningsson

CSE 307: Principles of Programming Languages

Back to OCaml. Summary of polymorphism. Example 1. Type inference. Example 2. Example 2. Subtype. Polymorphic types allow us to reuse code.

Reflection. Based on

CMSC330 Fall 2015 Midterm #1 12:30pm/2:00pm/5:00pm

System Software Assignment 1 Runtime Support for Procedures

CMSC330 Spring 2016 Midterm #1 9:30am/12:30pm/3:30pm

CMSC 330: Organization of Programming Languages

G Programming Languages Spring 2010 Lecture 4. Robert Grimm, New York University

CMSC 330: Organization of Programming Languages. Ownership, References, and Lifetimes in Rust

Functional Programming

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Winter 2013

Names and Types. standard hue names. Dr. Philip Cannata 1

Compiler construction

Principles of Programming Languages Topic: Scope and Memory Professor Louis Steinberg Fall 2004

CMSC 330: Organization of Programming Languages. OCaml Data Types

Lecture #23: Conversion and Type Inference

Conversion vs. Subtyping. Lecture #23: Conversion and Type Inference. Integer Conversions. Conversions: Implicit vs. Explicit. Object x = "Hello";

Recap: Functions as first-class values

CMSC330 Spring 2008 Final Exam

Chapter 1. Fundamentals of Higher Order Programming

Functional Programming. Pure Functional Programming

CS1622. Semantic Analysis. The Compiler So Far. Lecture 15 Semantic Analysis. How to build symbol tables How to use them to find

CMSC330 Fall 2016 Midterm #1 2:00pm/3:30pm

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

The role of semantic analysis in a compiler

Semantic Processing. Semantic Errors. Semantics - Part 1. Semantics - Part 1

CMSC 330: Organization of Programming Languages

Principles of Programming Languages COMP251: Functional Programming in Scheme (and LISP)

CMSC330 Fall 2014 Midterm 2 Solutions

Lecture 4 Memory Management

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Fall 2011

Design Issues. Subroutines and Control Abstraction. Subroutines and Control Abstraction. CSC 4101: Programming Languages 1. Textbook, Chapter 8

Programming Language Features. CMSC 330: Organization of Programming Languages. Turing Completeness. Turing Machine.

CMSC 330: Organization of Programming Languages

G Programming Languages - Fall 2012

CA Compiler Construction

Carlos Varela RPI September 19, Adapted with permission from: Seif Haridi KTH Peter Van Roy UCL

CS Lectures 2-3. Introduction to OCaml. Polyvios Pratikakis

Announcements. My office hours are today in Gates 160 from 1PM-3PM. Programming Project 3 checkpoint due tomorrow night at 11:59PM.

Procedure and Object- Oriented Abstraction

Semantic Analysis. Outline. The role of semantic analysis in a compiler. Scope. Types. Where we are. The Compiler Front-End

To figure this out we need a more precise understanding of how ML works

CS558 Programming Languages

Transcription:

CMSC 330: Organization of Programming Languages Closures (Implementing Higher Order Functions) CMSC 330 - Summer 2017 1

Returning Functions as Results In OCaml you can pass functions as arguments to map, fold, etc. and return functions as results let pick_fn n = let plus_three x = x + 3 in let plus_four x = x + 4 in if n > 0 then plus_three else plus_four pick_fn : int -> (int->int) Here, pick_fn takes an int argument, and returns a function CMSC 330 - Summer 2017 2

Multi-argument Functions Consider a rewriting of the previous code let pick_fn n = if n > 0 then (fun x->x+3) else (fun x->x+4) Here s another version let pick_fn n = (fun x -> if n > 0 then x+3 else x+4) which is just shorthand for let pick_fn n x = if n > 0 then x+3 else x+4 I.e., a multi-argument function! CMSC 330 - Summer 2017 3

Currying We just saw a way for a function to take multiple arguments! The function consumes one argument and returns a function that takes the rest This is called currying the function Named after the logician Haskell B. Curry But Schönfinkel and Frege discovered it Ø So it should probably be called Schönfinkelizing or Fregging CMSC 330 - Summer 2017 4

Curried Functions In OCaml OCaml syntax defaults to currying. E.g., is identical to all of the following: Thus: add has type int -> (int -> int) add 3 has type int -> int Ø add 3 is a function that adds 3 to its argument (add 3) 4 = 7 This works for any number of arguments CMSC 330 - Summer 2017 let add x y = x + y let add = (fun x -> (fun y -> x + y)) let add = (fun x y -> x + y) let add x = (fun y -> x+y) 5

Syntax Conventions for Currying Because currying is so common, OCaml uses the following conventions: -> associates to the right Ø Thus int -> int -> int is the same as Ø int -> (int -> int) function application associates to the left Ø Thus add 3 4 is the same as Ø (add 3) 4 CMSC 330 - Summer 2017 6

Another Example Of Currying A curried add function with three arguments: The same as let add_th x y z = x + y + z let add_th x = (fun y -> (fun z -> x+y+z)) Then... add_th has type int -> (int -> (int -> int)) add_th 4 has type int -> (int -> int) add_th 4 5 has type int -> int add_th 4 5 6 is 15 CMSC 330 - Summer 2017 7

Syntax trick: function vs. fun Syntax fun x y z -> e for curried functions Syntax function ps for single-argument funcs Where ps has the form p1 -> e1 pn -> en Permits more expressive patterns. E.g., can write this as this let rec sum l = match l with [] -> 0 (h::t) -> h + (sum t) let rec sum = function [] -> 0 (h::t) -> h + (sum t) CMSC 330 - Summer 2017 8

Currying is Standard In OCaml Pretty much all functions are curried Like the standard library map, fold, etc. See /usr/local/ocaml/lib/ocaml on Grace Ø In particular, look at the file list.ml for standard list functions Ø Access these functions using List.<fn name> Ø E.g., List.hd, List.length, List.map OCaml works hard to make currying efficient Because otherwise it would do a lot of useless allocation and destruction of closures What are those, you ask? Let s see CMSC 330 - Summer 2017 9

Quiz 1: What is enabled by currying? A. Passing functions as arguments B. Converting easily between tuples and multiple arguments C. Passing only a portion of the expected arguments D. Naming arguments CMSC 330 - Summer 2017 10

Quiz 1: What is enabled by currying? A. Passing functions as arguments B. Converting easily between tuples and multiple arguments C. Passing only a portion of the expected arguments D. Naming arguments CMSC 330 - Summer 2017 11

Quiz 2: Which f definition is equivalent? let f a b = a / b;; A. let f = (fun b -> (fun a -> a / b));; B. let f = function a b -> a / b;; C. let f (a, b) = a / b;; D. let f = (fun a -> (fun b -> a / b));; CMSC 330 - Summer 2017 12

Quiz 2: Which f definition is equivalent? let f a b = a / b;; A. let f = (fun b -> (fun a -> a / b));; B. let f = function a b -> a / b;; C. let f (a, b) = a / b;; D. let f = (fun a -> (fun b -> a / b));; CMSC 330 - Summer 2017 13

How Do We Implement Currying? Implementing currying is tricky. Consider: let addn n l = let add x = n + x in map add l (Equivalent to...) Accessing variable from outer scope let addn n = (fun l -> map (fun x -> n + x) l) When the anonymous function is called by map, n may not be on the stack any more! Ø We need some way to keep n around after addn returns CMSC 330 - Summer 2017 14

The Call Stack in C/Java/etc. void f(void) { int x; x = g(3); } int g(int x) { int y; y = h(x); return y; } int h (int z) { return z + 1; } int main(){ f(); return 0; } x <junk> 4 x 3 y <junk> 4 z 3 f g h CMSC 330 - Summer 2017 15

Now Consider Returning Functions let map f n = match n with [] -> [] (h::t) -> (f h)::(map f t) let addn n l = let add x = n + x in map add l addn 3 [1; 2; 3] n 3 l f n x 1 <list> <add> Uh oh...how does add know the value of n? OCaml does not read it off the stack Ø The language could do this, but can be confusing (see above) OCaml uses static scoping like C, C++, Java, and Ruby CMSC 330 - Summer 2017 16

Static Scoping (aka Lexical Scoping) In static or lexical scoping, (nonlocal) names refer to their nearest binding in the program text Going from inner to outer scope In our example, add refers to addn s n C example: Refers to the x at file scope that s the nearest x going from inner scope to outer scope in the source code int x; void f() { x = 3; } void g() { char *x = "hello"; f(); } CMSC 330 - Summer 2017 17

Closures Implement Static Scoping An environment is a mapping from variable names to values Just like a stack frame A closure is a pair (f, e) consisting of function code f and an environment e When you invoke a closure, f is evaluated using e to look up variable bindings CMSC 330 - Summer 2017 18

Example Closure 1 let add x = (fun y -> x + y) (add 3) 4 <cl> 4 3 + 4 7 Closure Function Environment CMSC 330 - Summer 2017 19

Example Closure 2 let mult_sum (x, y) = let z = x + y in fun w -> w * z (mult_sum (3, 4)) 5 <cl> 5 5 * 7 35 CMSC 330 - Summer 2017 20

Example Closure 3 let twice (n, y) = let f x = x + n in f (f y) twice (3, 4) <cl> (<cl> 4) <cl> 7 10 CMSC 330 - Summer 2017 21

Example Closure 4 let add x = (fun y -> (fun z -> x + y + z)) add( ) took 3 arguments? The compiler figures this out and avoids making closures (((add 1) 2) 3) ((<cl> 2) 3) (<cl> 3) 1+2+3 CMSC 330 - Summer 2017 22

Quiz 3: What is x? A. 10 B. 1 C. 15 let a = 0;; let b = 1;; let b = 10;; let f () = a + b;; let a = 5;; let x = f ();; D. Error - variable name conflicts CMSC 330 - Summer 2017 23

Quiz 3: What is x? A. 10 B. 1 C. 15 let a = 0;; let b = 1;; let b = 10;; let f () = a + b;; let a = 5;; let x = f ();; D. Error - variable name conflicts CMSC 330 - Summer 2017 24

Quiz 4: What is z? A. -1 B. 7 C. -2 let f x y = x - y in let g = f 2 in let x = 3 in let z = g 4 in z;; D. Type Error insufficient arguments CMSC 330 - Summer 2017 25

Quiz 4: What is z? A. -1 B. 7 C. -2 let f x y = x - y in let g = f 2 in let x = 3 in let z = g 4 in z;; D. Type Error insufficient arguments CMSC 330 - Summer 2017 26

Quiz 5: What is z? A. Type Error B. 0 C. Infinite loop D. 2 let f x = let rec g y = if y = 0 then x else g (y-1) in (fun z -> g z) in let z = f 2 0 in z;; CMSC 330 - Summer 2017 27

Quiz 5: What is z? A. Type Error B. 0 C. Infinite loop D. 2 let f x = let rec g y = if y = 0 then x else g (y-1) in (fun z -> g z) in let z = f 2 0 in z;; CMSC 330 - Summer 2017 28

Higher-Order Functions in C C supports function pointers typedef int (*int_func)(int); void app(int_func f, int *a, int n) { for (int i = 0; i < n; i++) a[i] = f(a[i]); } int add_one(int x) { return x + 1; } int main() { int a[] = {5, 6, 7}; app(add_one, a, 3); } CMSC 330 - Summer 2017 29

Higher-Order Functions in C (cont.) C does not support closures Since no nested functions allowed Unbound symbols always in global scope int y = 1; void app(int(*f)(int), n) { return f(n); } int add_y(int x) { return x + y; } int main() { app(add_y, 2); } CMSC 330 - Summer 2017 30

Higher-Order Functions in C (cont.) Cannot access non-local variables in C OCaml code let add x y = x + y Equivalent code in C is illegal int (* add(int x))(int) { return add_y; } int add_y(int y) { return x + y; /* compiler error: x undefined */ } CMSC 330 - Summer 2017 31

Higher-Order Functions in C (cont.) OCaml code let add x y = x + y Works if C supports nested functions Not in ISO C, but in gcc; but not allowed to return them int (* add(int x))(int) { int add_y(int y) { return x + y; } return add_y; } Does not allocate closure, so x popped from stack and add_y will get garbage (potentially) when called CMSC 330 - Summer 2017 32

Higher-Order Functions in Ruby Ruby supports higher-order functions Use yield within method to call code block argument def my_collect(a) b = Array.new(a.length) 0.upto(a.length-1) { i b[i] = yield(a[i]) } return b end b = my_collect([5, 6, 7]) { x x+1 } CMSC 330 - Summer 2017 33

Higher-Order Functions in Ruby (cont.) Ruby supports closures Code blocks can access non-local variables Binding determined by lexical scoping def twice yield yield end x = 1 twice {x += 1} puts x # 3 def twice x = 0 #dynamic yield yield end x = 1 #lexical twice {x += 1} puts x # 3 not 1 CMSC 330 - Summer 2017 34

Higher-Order Functions in Ruby (cont.) Ruby code blocks are actual variables def twice # implicit block yield # invoked with yield yield end twice { x += 1 } # same as x += 2 def quad (&block) # explicit block twice (&block) # used as argument twice (&block) end quad { x += 1 } # same as x += 4 CMSC 330 - Summer 2017 35

Higher-Order Functions in Ruby (cont.) Code blocks may be saved def quad (&block) # explicit block c = block # no ampersand! twice (c) # used as argument twice (c) end def twice c # arg = explicit closure c.call # invoke with.call c.call end quad { x += 1 } # same as x += 4 CMSC 330 - Summer 2017 36

Higher-Order Functions in Ruby (cont.) Ruby supports creating closures directly Proc.new proc lambda method c1 = Proc.new { x+=1 } c2 = proc { x+=1 } c3 = lambda { x+=1 } def foo x+=1 end c4 = method { :foo } c.call # x+=1 CMSC 330 - Summer 2017 37

Higher-Order Functions in Java/C++ An object in Java or C++ is kind of like a closure It has some data (like an environment) Along with some methods (i.e., function code) So objects can be used to simulate closures So is an anonymous Java inner class Inner class methods can access fields of outer class Back in CMSC 132 (OOP II) We studied how to implement some functional patterns in OO languages CMSC 330 - Summer 2017 38

Java 8 Supports Lambda Expressions Ocaml s fun (a, b) -> a + b Is like the following in Java 8 (a, b) -> a + b Java 8 supports closures, and variations on this syntax CMSC 330 - Summer 2017 39

Java 8 Example public class Calculator { } interface IntegerMath { int operation(int a, int b); } public int operatebinary(int a, int b, IntegerMath op) { return op.operation(a, b); } public static void main(string... args) { } Calculator myapp = new Calculator(); IntegerMath addition = (a, b) -> a + b; IntegerMath subtraction = (a, b) -> a - b; System.out.println("40 + 2 = " + myapp.operatebinary(40, 2, addition)); System.out.println("20-10 = " + myapp.operatebinary(20, 10, subtraction)); Lambda expressions CMSC 330 - Summer 2017 40