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

Similar documents
Chapter 11 :: Functional Languages

4/19/2018. Chapter 11 :: Functional Languages

Programming Language Pragmatics

Functional Languages. Hwansoo Han

Functional Programming. Big Picture. Design of Programming Languages

Programming Languages

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

Functional Programming

LECTURE 16. Functional Programming

Functional Programming. Pure Functional Languages

Functional Programming

Organization of Programming Languages CS3200/5200N. Lecture 11

CS 11 Haskell track: lecture 1

Fundamentals of Artificial Intelligence COMP221: Functional Programming in Scheme (and LISP)

Functional Programming. Pure Functional Languages

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

Imperative languages

Lambda Calculus see notes on Lambda Calculus

Functional Programming. Pure Functional Programming

Functional Programming Languages (FPL)

UMBC CMSC 331 Final Exam

CSCI-GA Scripting Languages

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages. Lambda calculus

Scheme. Functional Programming. Lambda Calculus. CSC 4101: Programming Languages 1. Textbook, Sections , 13.7

CMSC330. Objects, Functional Programming, and lambda calculus

Functional Programming and λ Calculus. Amey Karkare Dept of CSE, IIT Kanpur

Programming Systems in Artificial Intelligence Functional Programming

FP Foundations, Scheme

Architecture of LISP Machines. Kshitij Sudan March 6, 2008

5. Introduction to the Lambda Calculus. Oscar Nierstrasz

Functional Languages. Programming Language Pragmatics. DOI: /B Copyright 2009 by Elsevier Inc. All rights reserved.

11/6/17. Functional programming. FP Foundations, Scheme (2) LISP Data Types. LISP Data Types. LISP Data Types. Scheme. LISP: John McCarthy 1958 MIT

CS 415 Midterm Exam Spring 2002

Programming Languages

Symbolic Programming. Dr. Zoran Duric () Symbolic Programming 1/ 89 August 28, / 89

Functional Programming Lecture 1: Introduction

A Small Interpreted Language

Concepts of Programming Languages

11/6/17. Outline. FP Foundations, Scheme. Imperative Languages. Functional Programming. Mathematical Foundations. Mathematical Foundations

Chapter 15. Functional Programming Languages

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

Introduction to Scheme

A Brief Introduction to Common Lisp

Lambda Calculus and Lambda notation in Lisp II. Based on Prof. Gotshalks notes on Lambda Calculus and Chapter 9 in Wilensky.

CS 6110 S14 Lecture 1 Introduction 24 January 2014

CPS 506 Comparative Programming Languages. Programming Language Paradigm

SOFTWARE ARCHITECTURE 6. LISP

CS 314 Principles of Programming Languages

CMSC 331 Final Exam Section 0201 December 18, 2000

Introduction to LISP. York University Department of Computer Science and Engineering. York University- CSE V.

CMSC 330: Organization of Programming Languages

Principles of Programming Languages 2017W, Functional Programming

INF4820: Algorithms for Artificial Intelligence and Natural Language Processing. Common Lisp Fundamentals

Modern Programming Languages. Lecture LISP Programming Language An Introduction

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

Chapter 15. Functional Programming Languages

Lambda Calculus. Gunnar Gotshalks LC-1

Putting the fun in functional programming

Introduction to OCaml

CSE 413 Languages & Implementation. Hal Perkins Winter 2019 Structs, Implementing Languages (credits: Dan Grossman, CSE 341)

301AA - Advanced Programming [AP-2017]

CMSC 330: Organization of Programming Languages. Lambda Calculus

CS 242. Fundamentals. Reading: See last slide

Look at the outermost list first, evaluate each of its arguments, and use the results as arguments to the outermost operator.

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

Functional Programming

Racket. CSE341: Programming Languages Lecture 14 Introduction to Racket. Getting started. Racket vs. Scheme. Example.

CSc 372. Comparative Programming Languages. 2 : Functional Programming. Department of Computer Science University of Arizona

(Refer Slide Time: 4:00)

John McCarthy IBM 704

Introduction. chapter Functions

Introduction to ML. Mooly Sagiv. Cornell CS 3110 Data Structures and Functional Programming

Principles of Programming Languages

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

Functional Programming with Common Lisp

CIS4/681 { Articial Intelligence 2 > (insert-sort '( )) ( ) 2 More Complicated Recursion So far everything we have dened requires

FUNKCIONÁLNÍ A LOGICKÉ PROGRAMOVÁNÍ 2. ÚVOD DO LISPU: ATOMY, SEZNAMY, FUNKCE,

1.3. Conditional expressions To express case distinctions like

An Introduction to Scheme

CSCI B522 Lecture 11 Naming and Scope 8 Oct, 2009

Names, Bindings, Scopes

Lambda Calculus LC-1

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

One of a number of approaches to a mathematical challenge at the time (1930): Constructibility

Test 1 Summer 2014 Multiple Choice. Write your answer to the LEFT of each problem. 5 points each 1. Preprocessor macros are associated with: A. C B.

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

CMSC 330: Organization of Programming Languages

Robot Programming with Lisp

Streams, Delayed Evaluation and a Normal Order Interpreter. CS 550 Programming Languages Jeremy Johnson

CS 360 Programming Languages Interpreters

CMSC 330: Organization of Programming Languages

Polymorphism and Type Inference

COP4020 Programming Assignment 1 - Spring 2011

CMSC 330: Organization of Programming Languages. Lambda Calculus

Lecture 13 CIS 341: COMPILERS

Topic III. LISP : functions, recursion, and lists References: Chapter 3 of Concepts in programming languages by J. C. Mitchell. CUP, 2003.

Haskell Review COMP360

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

CSCC24 Functional Programming Scheme Part 2

Lambda Calculus. CS 550 Programming Languages Jeremy Johnson

Transcription:

Functional Languages CSE 307 Principles of Programming Languages Stony Brook University http://www.cs.stonybrook.edu/~cse307 1

Historical Origins 2 The imperative and functional models grew out of work undertaken Alan Turing, Alonzo Church, Stephen Kleene, Emil Post, etc. ~1930s different formalizations of the notion of an algorithm, or effective procedure, based on automata, symbolic manipulation, recursive function definitions, and combinatorics These results led Church to conjecture that any intuitively appealing model of computing would be equally powerful as well this conjecture is known as Church s thesis

Historical Origins Turing s model of computing was the Turing machine a sort of pushdown automaton using an unbounded storage tape the Turing machine computes in an imperative way, by changing the values in cells of its tape like variables just as a high level imperative program computes by changing the values of variables 3

Historical Origins 4 Church s model of computing is called the lambda calculus based on the notion of parameterized expressions with each parameter introduced by an occurrence of the letter λ. Lambda calculus was the inspiration for functional programming. Computation by substitution of parameters into expressions, just as computation by passing arguments to functions. Constructive proof that transforms input into output

Lambda Calculus λ = lambda lambda terms consist of: variables (a) lambda abstraction (λa.t) application (t s) Variables can be bound by lambda abstractions or free: Example: in λa.ab, a is bound, b is free. 5

Lambda Calculus alpha equivalence: λa.a = λb.b beta substitution: (λa.aa) b = bb problem: what happens if we substitute a free variable into a place where it would be bound? Example: (λa.(λb.ab)) b c wrong: (λb.λb) c cc right: use alpha equivalence to ensure this doesn't happen. (λa.(λd.ad)) b c (λd.bd) c bc 6

Functional Programming Concepts Functional languages such as Lisp, Scheme, FP, ML, Miranda, and Haskell are an attempt to realize Church's lambda calculus in practical form as a programming language The key idea: do everything by composing functions no mutable state no side effects So how do you get anything done in a functional language? Recursion takes the place of iteration First-call functions take value inputs Higher-order functions take a function as input 7

Functional Programming Concepts Recursion even does a nifty job of replacing looping x := 0; i := 1; j := 100; while i < j do x := x + i*j; i := i + 1; j := j - 1 end while return x becomes f(0,1,100), where f(x,i,j) == if i < j then f (x+i*j, i+1, j-1) else x 8

Functional Programming Concepts Necessary features, many of which are missing in some imperative languages: high-order functions powerful list facilities structured function returns fully general aggregates garbage collection 9

Functional Programming Concepts 10 LISP family of programming languages: Pure (original) Lisp Interlisp, MacLisp, Emacs Lisp Common Lisp Scheme All of them use s-expression syntax: (+ 1 2). LISP is old - dates back to 1958 - only Fortran is older. Anything in parentheses is a function call (unless quoted) (+ 1 2) evaluates to 3 ((+ 1 2)) <- error, since 3 is not a function. by default, s-expressions are evaluated. We can use the quote special form to stop that: (quote (1 2 3)) short form: '(1 2 3) is a list containing +, 1, 2

Functional Programming Concepts Pure Lisp is purely functional; all other Lisps have imperative features All early Lisps: dynamically scoped Not clear whether this was deliberate or if it happened by accident Scheme and Common Lisp are statically scoped Common Lisp provides dynamic scope as an option for explicitly-declared special functions Common Lisp now THE standard Lisp Very big; complicated 11

A Review/Overview of Scheme Interpreter runs a read-eval-print loop Things typed into the interpreter are evaluated (recursively) once Names: Scheme is generally a lot more liberal with the names it allows: foo? bar+ baz- <--- all valid names x$_%l&=*! <--- valid name names by default evaluate to their value 12

A Review/Overview of Scheme 13 Conditional expressions: (if a b c) = if a then b else c Example: (if (< 2 3) 4 5) 4 Example 2: only one of the sub-expressions evaluates (based on if the condition is true): (if (> a b) (- a 100) (- b 100)) Imperative stuff assignments sequencing (begin) iteration I/O (read, display)

A Review/Overview of Scheme Lamba expressions: (lambda (x) (* x x)) We can apply one or more parameters to it: ((lambda (x) (* x x)) 3) (* 3 3) 9 Bindings: (let ((a 1) (b 2)) (+ a b)) in let, all names are bound at once. So if we did: (let ((a 1) (b a)) (+ a b)) we'd get name from outer scope. It prevents recursive calls. letrec puts bindings into effect while being computed (allows for recursive calls): (letrec ((fac (lambda (x) (if (= x 0) 1 (* x (fac (- x 1))))))) (fac 10)) 14

A Review/Overview of Scheme Define binds a name in the global scope: (define square (lambda (x) (* x x))) Lists: pull apart lists: (car '(1 2 3)) -> 1 (cdr '(1 2 3)) -> (2 3) (cons 1 '(2 3)) -> (1 2 3) Equality testing: (= a b) <- numeric equality (eq? 1 2) <- shallow comparison (equal? a b) <- deep comparison 15

A Review/Overview of Scheme Control-flow: (begin (display "foo") (display "bar") ) Special functions: eval = takes a list and evaluates it. A list: '(+ 1 2) -> (+ 1 2) Evaluation of a list: (eval '(+ 1 2)) -> 3 apply = take a lambda and list: calls the function with the list as an argument. 16

A Review/Overview of Scheme Evaluation order: applicative order: evaluates arguments before passing them to a function: ((lambda (x) (* x x)) (+ 1 2)) ((lambda (x) (* x x) 3) (* 3 3) 9 normal order: passes in arguments before evaluating them: ((lambda (x) (* x x)) (+ 1 2)) (* (+ 1 2) (+ 1 2)) (* 3 3) 9 Note: we might want normal order in some code. (if-tuesday (do-tuesday)) // do-tuesday might print something and we want it only if it s Tuesday 17

A Review/Overview of Scheme 18 ((lambda (x y) (if x (+ y y) 0) t (* 10 10)) Applicative order: ((lambda (x y) (if x (+ y y)) t 100) (if t (+ 100 100) 0) (+ 100 100) 200 (four steps!) Normal Order: (if t (+ (* 10 10) (* 10 10)) 0) (+ (* 10 10) (* 10 10)) (+ 100 (* 10 10)) (+ 100 100) 200 (five steps!)

A Review/Overview of Scheme What if we passed in nil instead? ((lambda (x y) (if x (+ y y) 0) nil (* 10 10)) Applicative: ((lambda (x y) (if x (+ y y)) nil 100) (if nil (+ 100 100) 0) 0 (three steps!) Normal (if nil (+ (* 10 10) (* 10 10)) 0) 0 (two steps) Both applicative and normal order can do extra work! Applicative is usually faster, and doesn't require us to pass around closures all the time. 19

A Review/Overview of Scheme 20 Strict vs Non-Strict: We can have code that has an undefined result. (f) is undefined for (define f (lambda () (f))) - infinite recursion (define f (lambda () (/ 1 0)) - divide by 0. A pure function is: strict if it is undefined when any of its arguments is undefined, non-strict if it is defined even when one of its arguments is undefined. Applicative order == strict. Normal order == can be non-strict. ML, Scheme (except for macros) == strict. Haskell == nonstrict.

A Review/Overview of Scheme 21 Lazy Evaluation: Combines non-strictness of normal-order evaluation with the speed of applicative order. Idea: - Pass in closure. - Evaluate it once. - Store result in memo. - Next time, just return memo. Example 1: ((lambda (a b) (if a (+ b b) nil)) t (expensivefunc)) (if t (+ (expensivefunc) (expensivefunc)) nil) (+ (expensivefunc) (expensivefunc)) (+ 42 (expensivefunc)) <- takes a long time. (+ 42 42) <- very fast. 84 Example2: ((lambda (a b) (if a (+ b b) nil)) nil (expensivefunc)) (if nil (+ (expensivefunc) (expensivefunc)) nil) nil never evaluated expensivefunc! win!

22 Currying Named for Haskell Curry Example: let a function add that take two arguments: int add(int a, int b) { return a + b; } with the type signature: (int, int) -> int, i.e., takes 2 integers, returns an int. We can curry this, to create a function with signature: int -> (int -> int) using the curried version: f = add(1) print f(2) -> prints out 3. Really useful in practice, even in non-fp languages. Some languages use currying as their main function-calling semantics (ML): fun add a b : int = a + b; ML's calling conventions make this easier to work with: add 1 add 1 2 (There's no need to delimit arguments.)

Pattern Matching It's common for FP languages to include pattern matching operations: matching on value, matching on type, matching on structure (useful for lists). ML example: fun sum_even l = case l of nil => 0 b :: nil => 0 a :: b :: t => h + sum_even t; 23

Memoization Caching Results of Previous Computations (LISP): (defun fib (n) (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2))))) (setf memo-fib (memo #'fib)) (funcall memo-fib 3) => 3 (fib 5) => 8 (fib 6) => 13) 24

LISP (+ 2 2) => 4 (+ 1 2 3 4 5 6 7 8 9 10) => 55 (- (+ 9000 900 90 9) (+ 5000 500 50 5)) => 4444) (append '(Pat Kim) '(Robin Sandy)) => (PAT KIM ROBIN SANDY) '(pat Kim) => (PAT KIM)) 25

LISP (setf p '(John Q Public)) (first p)) (rest p)) (second p)) (third p)) (fourth p)) (length p)) (setf names '((John Q Public) (Malcolm X) (Miss Scarlet)) (first (first names)) => JOHN) (apply #'+ '(1 2 3 4)) => 10 26

LISP 27 (remove 1 '(1 2 3 2 1 0-1)) => (2 3 2 0-1) Destructive lists: (setq x '(a b c)) (setq y '(1 2 3)) (nconc x y) => (a b c 1 2 3) x => (a b c 1 2 3) y => (1 2 3)

A Bit of OCaml OCaml is a descendent of ML, and cousin to Haskell, F# O stands for objective, referencing the object orientation introduced in the 1990s Interpreter runs a read-eval-print loop like in Scheme Things typed into the interpreter are evaluated (recursively) once Parentheses are NOT function calls, but indicate tuples 28

A Bit of OCaml 29 Ocaml: Boolean values Numbers Chars Strings More complex types created by lists, arrays, records, objects, etc. (+ - * /) for ints, (+. -. *. /.) for floats let keyword for creating new names let average = fun x y -> (x +. y) /. 2.;;

A Bit of OCaml Ocaml: Variant Types type 'a tree = Empty Node of 'a * 'a tree * 'a tree;; Pattern matching let atomic_number (s, n, w) = n;; let mercury = ("Hg", 80, 200.592);; atomic_number mercury;; 80 30

A Bit of OCaml OCaml: Different assignments for references := and array elements <- let insertion_sort a = for i = 1 to Array.length a - 1 do let t = a.(i) in let j = ref i in while!j > 0 && t < a.(!j - 1) do done; done;; a.(!j) <- a.(!j - 1); j :=!j - 1 a.(!j) <- t 31

A Bit of OCaml OCaml: Different assignments for references := and array elements <- let insertion_sort a = for i = 1 to Array.length a - 1 do let t = a.(i) in let j = ref i in while!j > 0 && t < a.(!j - 1) do done; done;; a.(!j) <- a.(!j - 1); j :=!j - 1 a.(!j) <- t 32

Functional Programming in Perspective Advantages of functional languages lack of side effects makes programs easier to understand lack of explicit evaluation order (in some languages) offers possibility of parallel evaluation (e.g. MultiLisp) lack of side effects and explicit evaluation order simplifies some things for a compiler programs are often surprisingly short language can be extremely small and yet powerful 33

Functional Programming in Perspective Problems difficult (but not impossible!) to implement efficiently on von Neumann machines lots of copying of data through parameters frequent procedure calls heavy space use for recursion requires garbage collection requires a different mode of thinking by the programmer difficult to integrate I/O into purely functional model 34

Functional Programming in Perspective Other languages are embracing and integrating the concepts of Functional Programming: Java 8 - Higher Order Functions: Methods: Math#add(int, int) static Math#add(int)(int) dynamic method If an interface contains one method, then a method with the right signature can be an instance that implements that interface: button.addactionlistener(this#onbutton(actionevent)) Also adds inner methods, anonymous inner methods. 35