Higher-Order Functions

Similar documents
Higher-Order Functions (Part I)

Cost of Substitution

Threads. {seqn {spawn EXPR 1 } {spawn EXPR 2 }} Runs EXPR 1 and EXPR 2 in any order, even interleaved with each other

Typed Recursion {with {mk-rec : (((num -> num) -> (num -> num)) -> (num -> num)) {fun {body : ((num -> num) -> (num -> num))} {{fun {fx :

An Introduction to Functions

cs173: Programming Languages Final Exam

Non-Functional Procedures

Implementing Recursion

cs173: Programming Languages Midterm Exam

Running FAE Programs Natively

Functions and Recursion. Dr. Philip Cannata 1

Functions & First Class Function Values

Implementing Continuations

Type Declarations. [... <id> τ... ] <id> : τ. Γ <num> : number. Γ true : boolean. Γ false : boolean. Γ e 1 : number.

"Good" vs. "Bad" Expressions. ; interp-expr FAE... -> FAE-Value

State. Substitution relies on an identifer having a fxed value

Type Soundness. Type soundness is a theorem of the form If e : τ, then running e never produces an error

Type Declarations. Γ <num> : num [... <id> τ... ] <id> : τ Γ true : bool Γ false : bool Γ e 1 : num Γ e 2 : num Γ. {+ e 1 e 2 } : num

CPSC 311, 2011W1 Midterm Exam #2 2011/11/09

Types and evaluation

Quiz. Question #1: What is the value of the following expression? {+ 1 2} Wrong answer: 0 Wrong answer: 42. Answer: 3 1-4

From FP to OOP. Start with data: class Posn { int x; int y; Posn(int x, int y) { this.x = x; this.y = y; } }

Parsing Scheme (+ (* 2 3) 1) * 1

Functional Programming. Pure Functional Programming

Name EID. (calc (parse '{+ {with {x {+ 5 5}} {with {y {- x 3}} {+ y y} } } z } ) )

Environments

Random Testing in 321

Procedures. EOPL3: Section 3.3 PROC and App B: SLLGEN

CPSC 311, 2010W1 Midterm Exam #2

Parsing II Top-down parsing. Comp 412

Fall Semester, The Metacircular Evaluator. Today we shift perspective from that of a user of computer langugaes to that of a designer of

Computer Science 21b (Spring Term, 2015) Structure and Interpretation of Computer Programs. Lexical addressing

Understanding Recursion

CS1 Recitation. Week 2

Administrative Stuff

CSE 341: Programming Languages

Comp 311: Sample Midterm Examination

CMSC 330: Organization of Programming Languages. Operational Semantics

Name SOLUTIONS EID NOTICE: CHEATING ON THE MIDTERM WILL RESULT IN AN F FOR THE COURSE.

Comp 411 Principles of Programming Languages Lecture 7 Meta-interpreters. Corky Cartwright January 26, 2018

Principles of Programming Languages

fjyswan Dr. Philip Cannata 1

Module 9: Trees. If you have not already, make sure you. Read How to Design Programs Sections 14, 15, CS 115 Module 9: Trees

Bindings & Substitution

Functions and Recursion

CS 342 Lecture 8 Data Abstraction By: Hridesh Rajan

CS61A Midterm 2 Review (v1.1)

Reminder About Functions

APT Session 7: Compilers

CS115 - Module 10 - General Trees

A Functional Evaluation Model

CPSC W1 University of British Columbia

6.037 Lecture 4. Interpretation. What is an interpreter? Why do we need an interpreter? Stages of an interpreter. Role of each part of the interpreter

Random Testing in 321

Lecture 12: Conditional Expressions and Local Binding

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

CS2500 Exam 2 Fall 2011

An Explicit-Continuation Metacircular Evaluator

Parsing III. (Top-down parsing: recursive descent & LL(1) )

User-defined Functions. Conditional Expressions in Scheme

Discussion 12 The MCE (solutions)

APT Session 6: Compilers

CS61A Discussion Notes: Week 11: The Metacircular Evaluator By Greg Krimer, with slight modifications by Phoebus Chen (using notes from Todd Segal)

Functional Programming. Pure Functional Languages

cs173: Programming Languages

6.184 Lecture 4. Interpretation. Tweaked by Ben Vandiver Compiled by Mike Phillips Original material by Eric Grimson

Introduction to Scheme

Syntax Analysis, III Comp 412

regsim.scm ~/umb/cs450/ch5.base/ 1 11/11/13

Mid-Term 2 Grades

Closures & Environments. CS4410: Spring 2013

B The SLLGEN Parsing System

A Third Look At ML. Chapter Nine Modern Programming Languages, 2nd ed. 1

CS115 - Module 8 - Binary trees

Syntax Analysis, III Comp 412

Functional Programming. Pure Functional Languages

Fundamentals and lambda calculus. Deian Stefan (adopted from my & Edward Yang s CSE242 slides)

The Compiler So Far. CSC 4181 Compiler Construction. Semantic Analysis. Beyond Syntax. Goals of a Semantic Analyzer.

Parsing. Note by Baris Aktemur: Our slides are adapted from Cooper and Torczon s slides that they prepared for COMP 412 at Rice.

CS 314 Principles of Programming Languages. Lecture 16

6.037 Lecture 7B. Scheme Variants Normal Order Lazy Evaluation Streams

Programming Languages. Dr. Philip Cannata 1

Below are example solutions for each of the questions. These are not the only possible answers, but they are the most common ones.

CMPT 379 Compilers. Parse trees

Context-sensitive Analysis

A clarification on terminology: Recognizer: accepts or rejects strings in a language. Parser: recognizes and generates parse trees (imminent topic)

Lexical vs. Dynamic Scope

Intermediate Code Generation

(scheme-1) has lambda but NOT define

Data Abstraction. An Abstraction for Inductive Data Types. Philip W. L. Fong.

Principles of Programming Languages

Abstracting Definitional Interpreters

CMSC 330: Organization of Programming Languages. Lambda Calculus

1 Lexical Considerations

Functional Programming - 2. Higher Order Functions

Compilers. Type checking. Yannis Smaragdakis, U. Athens (original slides by Sam

Parsing. Zhenjiang Hu. May 31, June 7, June 14, All Right Reserved. National Institute of Informatics

Topic 3: Syntax Analysis I

M. Snyder, George Mason University LAMBDA CALCULUS. (untyped)

Fundamentals and lambda calculus

Transcription:

Higher-Order Functions 1

Why Functions as Values Abstraction is easier with functions as values abstract over add and sub cases filter, map, etc. What are objects? Callbacks? Separate deffun form becomes unnecessary {deffun {f x} {+ 1 x}} {f 10} {with {f {fun {x} {+ 1 x}}} {f 10}}

FWAE Grammar, Almost <FWAE> ::= <num> {+ <FWAE> <FWAE>} {- <FWAE> <FWAE>} {with {<id> <FWAE>} <FWAE>} <id> {<id> <FWAE>}? {fun {<id>} <FWAE>} NEW 5

FWAE Evaluation 10 10 {+ 1 2} 3 {- 1 2} -1 {with {x 7} {+ x 2}} {+ 7 2} 9 y free variable {fun {x} {+ 1 x}} {fun {x} {+ 1 x}} Result is not always a number! ; interp : FWAE?... -> FWAE-Value?

FWAE Evaluation {with {y 10} {fun {x} {+ y x}}} {fun {x} {+ 10 x}} {with {f {fun {x} {+ 1 x}}} {f 3}} {{fun {x} {+ 1 x}} 3} Doesn t match the grammar for <FWAE> 1 1

FWAE Grammar <FWAE> ::= <num> {+ <FWAE> <FWAE>} {- <FWAE> <FWAE>} {with {<id> <FWAE>} <FWAE>} <id> {<id> <FWAE>} {fun {<id>} <FWAE>} {<FWAE> <FWAE>} NEW NEW 15

FWAE Evaluation {with {f {fun {x} {+ 1 x}}} {f 3}} {{fun {x} {+ 1 x}} 3} {+ 1 3} 4 {{fun {x} {+ 1 x}} 3} {+ 1 3} 4 {1 2} not a function {+ 1 {fun {x} 10}} not a number 1 1

FWAE Datatype (define-type FWAE [num (n number?)] [add (lhs FWAE?) (rhs FWAE?)] [sub (lhs FWAE?) (rhs FWAE?)] [with (name symbol?) (named-expr FWAE?) (body FWAE?)] [id (name symbol?)] [fun (param symbol?) (body FWAE?)] [app (fun-expr FWAE?) (arg-expr FWAE?)]) (test (parse '{fun {x} {+ x 1}}) (fun 'x (add (id 'x) (num 1))))

FWAE Datatype (define-type FWAE [num (n number?)] [add (lhs FWAE?) (rhs FWAE?)] [sub (lhs FWAE?) (rhs FWAE?)] [with (name symbol?) (named-expr FWAE?) (body FWAE?)] [id (name symbol?)] [fun (param symbol?) (body FWAE?)] [app (fun-expr FWAE?) (arg-expr FWAE?)]) (test (parse '{{fun {x} {+ x 1}} 10}) (app (fun 'x (add (id 'x) (num 1))) (num 10)))

FWAE-Value (define-type FWAE-Value [numv (n number?)] [funv (param symbol?) (body FWAE?)]) 5

FWAE Interpreter ; interp : FWAE? -> FWAE-Value? (define (interp an-fwae) (type-case FWAE an-fwae [num (n) (numv n)] [add (l r) (num+ (interp l) (interp r))] [sub (l r) (num- (interp l) (interp r))] [with (bound-id named-expr body-expr) (interp (subst body-expr bound-id (interp named-expr)))] [id (name) (error 'interp "free variable")] [fun (param body-expr) (funv param body-expr)] [app (fun-expr arg-expr) (local [(define fun-val (interp fun-expr))] (interp (subst (funv-body fun-val) (funv-param fun-val) (interp arg-expr))))]))

Better: Add and Subtract ; num+ : FWAE-Value? FWAE-Value? -> FWAE-Value? (define (num+ x y) (numv (+ (numv-n x) (numv-n y)))) ; num- : FWAE-Value? FWAE-Value? -> FWAE-Value? (define (num- x y) (numv (- (numv-n x) (numv-n y)))) ; ; ; num-op : (number? number? -> number?) -> (FWAE-Value? FWAE-Value? -> FWAE-Value?) (define (num-op op) (lambda (x y) (numv (op (numv-n x) (numv-n y))))) (define num+ (num-op +)) (define num- (num-op -)) 1

FWAE Subst ; subst : FWAE? symbol? FWAE-Value? -> FWAE? (define (subst exp sub-id val) (type-case FWAE exp... [id (name) (cond [(equal? name sub-id) (type-case FWAE-Value val [numv (n) (num n)] [funv (param body) (fun param body)]) [else exp]])]...))

FWAE Subst ; subst : FWAE? symbol? FWAE-Value? -> FWAE? (define (subst exp sub-id val) (type-case FWAE exp... [app (f arg) (app (subst f sub-id val) (subst arg sub-id val))] [fun (id body) (if (equal? sub-id id) exp (fun id (subst body sub-id val)))]))

FWAE Subst Beware: with the implementation on the previous slide, (subst {with {y 10} z} 'z {fun {x} {+ x y}} ) {with {y 10} {fun {x} {+ x y}}} which is wrong, but we ignore this problem Only happens when the original program has free variables The problem disappears with deferred substitution, anyway Solution: Capture-avoiding substitution Take Jesse s statics of PL or Christos s dynamics of PL 5

No More With Compare the with and app implementations: (define (interp an-fwae) (type-case FWAE an-fwae... [with (bound-id named-expr body-expr) (interp (subst body-expr bound-id (interp named-expr)))]... [app (fun-expr arg-expr) (local [(define fun-val (interp fun-expr))] (interp (subst (funv-body fun-val) (funv-param fun-val) (interp arg-expr))))])) The app case does everything that with does

No More With {with {x 10} x} is the same as {{fun {x} x} 10} In general, is the same as {with {<id> <FWAE> 1 } <FWAE> 2 } {{fun {<id>} <FWAE> 2 } <FWAE> 1 } Let s assume (test {with {<id> <FWAE> 1 } <FWAE> 2 } (app (fun '<id> <FWAE> 2 ) <FWAE> 1 ))

FAE Grammar <FAE> ::= <num> {+ <FAE> <FAE>} {- <FAE> <FAE>} {with {<id> <FAE>} <FAE>} <id> {fun {<id>} <FAE>} {<FAE> <FAE>} We ll still use with in example boxes No more case lines in interp, etc. for with No more test cases for interp, etc. using with 1

FAE Interpreter ; interp : FAE? -> FAE-Value? (define (interp a-fae) (type-case FAE a-fae [num (n) (numv n)] [add (l r) (num+ (interp l) (interp r))] [sub (l r) (num- (interp l) (interp r))] [id (name) (error 'interp "free variable")] [fun (param body-expr) a-fae] [app (fun-expr arg-expr) (local [(define fun-val (interp fun-expr))] (interp (subst (funv-body fun-val) (funv-param fun-val) (interp arg-expr))))]))

FAE with Deferred Substitution (interp {with {y 10} {fun {x} {+ y x}}} ) y = 10 (interp {fun {x} {+ y x}} ) (interp {{fun {y} {fun {x} {+ y x}}} 10} ) y = 10 (interp {fun {x} {+ y x}} )

FAE with Deferred Substitution (interp {{with {y 10} {fun {x} {+ y x}}} {with {y 7} y}} ) Argument expression: (interp {with {y 7} y} ) (interp y y = 7 ) 7 Function expression: (interp {with {y 10} {fun {x} {+ y x}}} ) y = 10 (interp {fun {x} {+ y x}} )?

FAE Values A function value needs to keep its substitution cache (define-type FAE-Value [numv (n number?)] [closurev (param symbol?) (body FAE?) (ds DefrdSub?)]) (define-type DefrdSub [mtsub] [asub (name symbol?) (value FAE-Value?) (ds DefrdSub?)]) (test (interp {with {y 10} {fun {x} {+ y x}}} ) (closurev 'x {+ y x} (asub 'y (num 10) (mtsub)))) 5 5

Continuing Evaluation y = 10 Function: {fun {x} {+ y x}} Argument: 7 To apply, interpret the function body with the given argument: (interp {+ y x} ) x = 7 y = 10 5 5

FAE Interpreter with Deferred Substitution ; interp : FAE? DefrdSub? -> FAE-Value? (define (interp a-fae ds) (type-case FAE a-fae [num (n) (numv n)] [add (l r) (num+ (interp l ds) (interp r ds))] [sub (l r) (num- (interp l ds) (interp r ds))] [id (name) (lookup name ds)] [fun (param body-expr) (closurev param body-expr ds)] [app (fun-expr arg-expr) (local [(define fun-val (interp fun-expr ds)) (define arg-val (interp arg-expr ds))] (interp (closurev-body fun-val) (asub (closurev-param fun-val) arg-val (closurev-ds fun-val))))])) 5