CSE 307: Principles of Programming Languages

Similar documents
CSE 307: Principles of Programming Languages

Why OCaml? Introduction to Objective Caml. Features of OCaml. Applications written in OCaml. Stefan Wehr

Introduction to Objective Caml

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

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

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

CSCI-GA Scripting Languages

Lists. Michael P. Fourman. February 2, 2010

CSC324- TUTORIAL 5. Shems Saleh* *Some slides inspired by/based on Afsaneh Fazly s slides

CIS24 Project #3. Student Name: Chun Chung Cheung Course Section: SA Date: 4/28/2003 Professor: Kopec. Subject: Functional Programming Language (ML)

Introduction to OCaml

The type checker will complain that the two branches have different types, one is string and the other is int

Topic 7: Algebraic Data Types

All the operations used in the expression are over integers. a takes a pair as argument. (a pair is also a tuple, or more specifically, a 2-tuple)

Introduction to ML. Based on materials by Vitaly Shmatikov. General-purpose, non-c-like, non-oo language. Related languages: Haskell, Ocaml, F#,

INTRODUCTION TO HASKELL

Haske k ll An introduction to Functional functional programming using Haskell Purely Lazy Example: QuickSort in Java Example: QuickSort in Haskell

An introduction introduction to functional functional programming programming using usin Haskell

Type Checking and Type Inference

Some Advanced ML Features

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

CSE 3302 Programming Languages Lecture 8: Functional Programming

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

Polymorphism and Type Inference

n n Try tutorial on front page to get started! n spring13/ n Stack Overflow!

COSE212: Programming Languages. Lecture 3 Functional Programming in OCaml

A general introduction to Functional Programming using Haskell

Functional Programming and Haskell

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

Functional Paradigm II

FUNCTIONAL PROGRAMMING

Handout 2 August 25, 2008

CS 457/557: Functional Languages

A quick introduction to SML

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

CSC/MAT-220: Lab 6. Due: 11/26/2018

Logic - CM0845 Introduction to Haskell

Functional Programming for Imperative Programmers

Haskell 98 in short! CPSC 449 Principles of Programming Languages

CS Lecture 6: Map and Fold. Prof. Clarkson Fall Today s music: Selections from the soundtrack to 2001: A Space Odyssey

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

PROGRAMMING IN HASKELL. CS Chapter 6 - Recursive Functions

Functional Programming in Haskell Part I : Basics

Introduction to OCaml

Lecture 19: Functions, Types and Data Structures in Haskell

Functional Programming. Big Picture. Design of Programming Languages

List Functions, and Higher-Order Functions

CMSC 330, Fall 2013, Practice Problem 3 Solutions

Programming Languages

Lists. Adrian Groza. Department of Computer Science Technical University of Cluj-Napoca

Haskell Overview II (2A) Young Won Lim 8/9/16

Haskell Introduction Lists Other Structures Data Structures. Haskell Introduction. Mark Snyder

General Computer Science (CH ) Fall 2016 SML Tutorial: Practice Problems

CS 11 Haskell track: lecture 1

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

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

CSCI-GA Final Exam

Introduction to SML Basic Types, Tuples, Lists, Trees and Higher-Order Functions

Scope and Introduction to Functional Languages. Review and Finish Scoping. Announcements. Assignment 3 due Thu at 11:55pm. Website has SML resources

Plan (next 4 weeks) 1. Fast forward. 2. Rewind. 3. Slow motion. Rapid introduction to what s in OCaml. Go over the pieces individually

INTRODUCTION TO FUNCTIONAL PROGRAMMING

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

SML A F unctional Functional Language Language Lecture 19

Functional Programming. Introduction To Cool

Patterns The Essence of Functional Programming

CS Lecture 6: Map and Fold. Prof. Clarkson Spring Today s music: Selections from the soundtrack to 2001: A Space Odyssey

According to Larry Wall (designer of PERL): a language by geniuses! for geniuses. Lecture 7: Haskell. Haskell 98. Haskell (cont) - Type-safe!

CSCC24 Functional Programming Typing, Scope, Exceptions ML

Homework 3 COSE212, Fall 2018

# true;; - : bool = true. # false;; - : bool = false 9/10/ // = {s (5, "hi", 3.2), c 4, a 1, b 5} 9/10/2017 4

CSC312 Principles of Programming Languages : Functional Programming Language. Copyright 2006 The McGraw-Hill Companies, Inc.

News. Programming Languages. Complex types: Lists. Recap: ML s Holy Trinity. CSE 130: Spring 2012

Inductive Data Types

Mini-ML. CS 502 Lecture 2 8/28/08

Programming in Omega Part 1. Tim Sheard Portland State University

Example: Haskell algebraic data types (1)

Haskell through HUGS THE BASICS

Part I. Language Core

Programming Language Concepts: Lecture 14

CSE 130 Programming Languages. Lecture 3: Datatypes. Ranjit Jhala UC San Diego

02157 Functional Programming Lecture 1: Introduction and Getting Started

Types and Type Inference

CSE 307: Principles of Programming Languages

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

Haskell 5.1 INTERACTIVE SESSIONS AND THE RUN-TIME SYSTEM

CS 321 Programming Languages

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

Polymorphism and Type Inference

Programming Paradigms

Types, Type Inference and Unification

Types and Type Inference

If we have a call. Now consider fastmap, a version of map that uses futures: Now look at the call. That is, instead of

Recap: ML s Holy Trinity. Story So Far... CSE 130 Programming Languages. Datatypes. A function is a value! Next: functions, but remember.

CSE 130 Programming Languages. Datatypes. Ranjit Jhala UC San Diego

Introduction to SML Getting Started

Topic 5: Examples and higher-order functions

Algebraic Types. Chapter 14 of Thompson

Imperative languages

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

Cunning Plan. One-Slide Summary. Functional Programming. Functional Programming. Introduction to COOL #1. Classroom Object-Oriented Language

Transcription:

CSE 307: Principles of Programming Languages Syntax R. Sekar 1 / 63 Topics 1. Introduction 2. Basics 3. Functions 4. Data Structures 5. Overview 6. OCAML Performance 2 / 63 Section 1 Introduction 3 / 63

Functional Programming Programs are viewed as functions transforming input to output Complex transformations are achieved by composing simpler functions (i.e. applying functions to results of other functions) Purely Functional Languages: Values given to variables do not change when a program is evaluated Variables are names for values, not names for storage locations. Functions have referential transparency: Value of a function depends solely on the values of its arguments Functions do not have side effects. Order of evaluation of arguments does not affect the value of a function s output. 4 / 63 Functional Programming (Contd.) Usually support complex (recursive) data types... with automatic allocation and deallocation of memory (e.g. garbage collection) No loops: recursion is the only way to structure repeated computations Functions themselves may be treated as values Higher-order functions: Functions that functions as arguments. Functions as first-class values: no arbitrary restrictions that distinguish functions from other data types (e.g. int) 5 / 63 History LISP ( 60) Scheme ( 80s): a dialect of LISP; more uniform treatment of functions ML ( 80s): Strong typing and type inference Standard ML (SML, SML/NJ: 90s) Categorical Abstract Machine Language (CAML, CAML Light, O CAML: late 90s) Haskell, Gofer, HUGS,... (late 90s): Lazy functional programming 6 / 63

ML Developed initially as a meta language for a theorem proving system (Logic of Computable Functions) The two main dialects, SML and CAML, have many features in common: data type definition, type inference, interactive top-level,... SML and CAML have different syntax for expressing the same things. For example: In SML: variables are defined using val and functions using fun In CAML: both variables and functions defined using equations. Both have multiple implementations (Moscow SML, SML/NJ; CAML, OCAML) with slightly different usage directives and module systems. 7 / 63 Section 2 Basics 8 / 63 OCAML CAML with object-oriented features. Compiler and run-time system that makes OCAML programs run with performance comparable imperative programs! A complete development environment including libraries building UIs, networking (sockets), etc. We will focus on the non-oo part of OCAML Standard ML (SML) has more familiar syntax. CAML has better library and runtime support and has been used in more real systems. 9 / 63

The OCAML System OCAML interactive toplevel Invocation: UNIX: Run ocaml from command line Windows: Run ocaml.exe from Command window or launch ocamlwin.exe from windows explorer. OCAML prompts with \# User can enter new function/value definitions, evaluate expressions, or issue OCAML directives at the prompt. Control-D to exit OCAML OCAML compiler: ocamlc to compile OCAML programs to object bytecode. ocamlopt to compile OCAML programs to native code. 10 / 63 Learning OCAML We will use OCAML interactive toplevel throughout for examples. What we type in can be entered into a file (i.e. made into a program ) and executed. Read David Matuszek s tutorial for a quick intro, then go to Jason Hickey s tutorial. To clarify syntax etc. see OCAML manual. (http://caml.inria.fr/tutorials-eng.html) 11 / 63 Expression Evaluation Syntax: expression ;; Two semicolons indicate the end of expression Example: User Input OCAML s Response 2 * 3;; - : int = 6 OCAML s response: - : The last value entered : : is of type int : integer = : and the value is 6 : 6 12 / 63

Expression Evaluation (Contd.) More examples: User Input OCAML s Response 2 + 3 * 4;; - : int = 14-2 + 3 * 4;; - : int = 10 (-2 + 3) * 4;; - : int = 4 4.4 ** 2.0;; - : float = 19.36 2 + 2.2;;... This expression has type float but is used here with type int 2.7 + 2.2;;... This expression has type float but is used here with type int 2.7 +. 2.2;; - : float = 4.9 Operators 13 / 63 Operators + - * / mod +. -. *. /. ** &&,, not Types Integer arithmetic Floating point arithmetic Boolean operations Value definitions 14 / 63 Syntax: let name = expression ;; Examples: User Input OCAML s Response let x = 1;; val x : int = 1 let y = x + 1;; val y : int = 2 let x = x + 1;; val x : int = 3 let z = "OCAML rocks!";; val z : string = "OCAML rocks!" let w = "21";; val w : string = "21" let v = int_of_string(w);; val v : int = 21 15 / 63

Section 3 Functions Functions 16 / 63 Syntax: let name { argument } = expression ;; Examples: User Input OCAML s Response let f x = 1;; val f : 'a -> int = <fun> let g x = x;; val g : 'a -> 'a = <fun> let inc x = x + 1;; val inc : int -> int = <fun> let sum(x,y) = x+y;; val sum : int * int -> int = <fun> let add x y = x+y;; val add : int -> int -> int = <fun> Note the use of parametric polymorphism in functions f and g More example functions let max(x, y) = val max : 'a * 'a -> 'a = <fun> if x < y then y else x;; let mul(x, y) = if x = 0 then 0 else y+mul(x-1,y);; Unbound value mul let rec mul(x, y) = val mul : int * int -> int = <fun> if x = 0 then 0 else y+mul(x-1,y);; let rec mul(x, y) = val mul : int * int -> int = <fun> if x = 0 then 0 else let i = mul(x-1,y) in y+i;; 17 / 63 18 / 63

Currying Named after H.B. Curry Curried functions take arguments one at a time, as opposed to taking a single tuple argument When provided with number of arguments less than the requisite number, result in a closure When additional arguments are provided to the closure, it can be evaluated 19 / 63 Currying Example Tuple version of a function fun add(x,y) = x+y:int; val add = fn int * int -> int Curried version of the same function fun addc x y = x+y:int; val addc = fn : int -> int -> int When addc is given one argument, it yields a function with type int -> int - add 2 3; - add 2; it = 5 : int; it = fn : int->int Recursion - it 3; it = 5 : int 20 / 63 Recursion is the means for iteration Consider the following examples fun f(0) = 0 f(n) = 2*f(n-1); fun g(0) = 1 g(1) = 1 g(n) = g(n-1)+g(n-2); fun h(0) = 1 h(n) = 2*h(n div 2); 21 / 63

Section 4 Data Structures 22 / 63 Built-in Data Structures: Lists and Tuples User Input OCAML s Response [1];; - : int list = [1] [4.1; 2.7; 3.1];; - : float list = [4.1; 2.7; 3.1] [4.1; 2];;... This expression has type int but is used here with type float [[1;2]; [4;8;16]];; - : int list list = [[1;2], [4;8;16]] 1::2::[] - : int list = [1; 2] 1::(2::[]) - : int list = [1; 2] (1,2);; - : int * int = (1, 2) ();; - : unit = () let (x,y) = (3,7);; val x : int = 3 val y : int = 7 23 / 63 Tuples (2,"Andrew") : int * string (true,3.5,"x") : bool * real * string ((4,2),(7,3)) : (int * int) * (int * int) Tuple components can be of different types, but lists must contain elements of same type [1,2,3] : int list ["Andrew","Ben"] : string list [(2,3),(2,2),(9,1)] : (int * int) list [[],[1],[1,2]] : int list list 24 / 63

Pattern Matching Used to deconstruct data structures. Example: let rec sumlist l = match l with [] -> 0 x::xs -> x + sumlist(xs);; When evaluating sumlist [2; 5] The argument [2; 5] matches the pattern x::xs,... setting x to 2 and xs to [5]... then evaluates 2 + sumlist([5]) 25 / 63 Pattern Matching (Contd.) match is analogous to a switch statement Each case describes a pattern (lhs of -> ) and an expression to be evaluated if that pattern is matched (rhs of -> ) patterns can be constants, or terms made up of constants and variables The different cases are separated by A matching pattern is found by searching in order (first case to last case) The first matching case is selected; others are discarded let emptylist l = match l with [] -> true _ -> false;; 26 / 63 Pattern Syntax Pattern syntax: Patterns may contain wildcards (i.e. _ ); each occurrence of a wildcard is treated as a new anonymous variable. Patterns are linear: any variable in a pattern can occur at most once. Pattern matching is used very often in OCAML programs. OCAML gives a shortcut for defining pattern matching in functions with one argument. Example: let rec sumlist l = match l with [] -> 0 x::xs -> x + sumlist(xs);; let rec sumlist = function [] -> 0 x::xs -> x + sumlist(xs);; 27 / 63

Functions on Lists Add one list to the end of another: let rec append v1 v2 = match v1 with [] -> v2 x::xs -> x::(append xs v2);; Note that this function has type append: 'a list -> 'a list -> 'a list and hence can be used to concatenate arbitrary lists, as long as the list elements are of the same type. This function is implemented by builtin operator @ Functions on Lists (Contd.) 28 / 63 Many list-processing functions are available in module Lists. Examples: Lists.hd: get the first element of the given list Lists.rev: reverse the given list User-defined Types 29 / 63 Enumerated types: A finite set of values Two values can be compared for equality There is no order among values Example: type primarycolor = RED GREEN BLUE;; type status = Freshman Sophomore Junior Senior;; Syntax: type name = name { name } ;; A note about names: Names of constants must begin with an uppercase letter. Names of types, functions and variables must begin with a lowercase letter. Names of constants are global within a module and not local to its type. 30 / 63

Record types Used to define structures with named fields. Example: type student = {name:string; gpa:float; year:status;};; Syntax: type name = { { name {: name ; } } ;; Usage: Creating records: let joe = {name="joe"; gpa=2.67; year=sophomore;};; Accessing fields: let x = joe.gpa;; (* using "." operator *) let {id=x} = joe;; (* using pattern matching *) Field names are global within a module and not local to its type. 31 / 63 Union types Used to define (possibly recursive) structured data with tags. Example: type itree = Node of int * itree * itree Empty;; The empty tree is denoted by Empty The tree with one node, with integer 2, is denoted by Node(2,Empty,Empty) Tree Denoted by 1 2 3 4 5 6 Node(1, Node(2, Node(4, Empty, Empty), Node(5, Empty, Empty)) Node(3, Empty, Node(6, Empty, Empty))) 32 / 63 Union Types (Contd.) Generalizes enumerated types Constants that tag the different structures in an union (e.g. Node and Empty) are called data constructors. Usage example: counting the number of elements in a tree: let rec nelems tree = match tree with Node(i, lst, rst) -> (* `i' is the value of the node; `lst' is the left sub tree; and `rst' is the right sub tree *) 1 + nelems lst + nelems rst Empty -> 0;; 33 / 63

Recursive Types Direct definition of recursive types is supported in SML using datatype declarations. - datatype intbtree = LEAF of int NODE of int * intbtree * intbtree; datatype intbtree = LEAF of int NODE of int * intbtree * intbtree We are defining a binary tree type inductively: Base case: a binary tree with one node, called a LEAF Induction case: construct a binary tree by constructing a new node that sores an integer value, and has two other binary trees as children Recursive Types (Contd.) 34 / 63 We may construct values of this type as follows: - val l = LEAF(1); val l = LEAF 1 : intbtree - val r = LEAF(3); val r = LEAF 3 : intbtree - val n = NODE(2, l, r); val n = NODE (2,LEAF 1,LEAF 3) : intbtree Recursive Types (Contd.) 35 / 63 Types can be mutually recursive. Consider: -datatype expr = PLUS of expr * expr = PROD of expr * expr = FUN of (string * exprs) = IVAL of int =and = exprs = EMPTY = LIST of expr * exprs; datatype expr = FUN of string * exprs PLUS of expr * expr PROD of expr * expr datatype exprs = EMPTY LIST of expr * exprs The key word and is used for mutually recursive type definitions. 36 / 63

Recursive Types (Contd.) We could also have defined expressions using the predefined list type: - datatype expr=plus of expr*expr PROD of expr*expr = FUN of string * expr list; datatype expr = FUN of string * expr list PLUS of expr * expr PROD of expr * expr Examples: The expression 3 + (4 * 5) can be represented as a value of the above datatype expr as follows 37 / 63 Recursive Types (Contd.) The following picture illustrates the structure of the value pl and how it is constructed from other values. val val val val val v3 = IVAL(3); v5 = IVAL(5); v4 = IVAL(4); pr = PROD(v5, v4); pl = PLUS(v3, pr); 38 / 63 Recursive Types (Contd.) Similarly, f(2,4,1) can be represented as: val a1 = EMPTY; val a2 = ARG(IVAL(4), a1); val a3 = ARG(IVAL(2), a2); val fv = FUN("f", a3); Note the use of expr list to refer to a list that consists of elements of type expr 39 / 63

Polymorphic Data Structures Structures whose components may be of arbitrary types. Example: type 'a tree = Node of 'a * 'a tree * 'a tree Empty;; 'a in the above example is a type variable... analogous to the typename parameters of a C++ template Parameteric polymorphism enforces that all elements of the tree are of the same type. Usage example: traversing a tree in preorder: let rec preorder tree = match tree with Node(i, lst, rst) -> i::(preorder lst)@(preorder rst) Empty -> [];; Parameterized Types 40 / 63 type (<typeparameters>) <typename> = <typeexpression> type ('a, 'b) pairlist = ('a * 'b) list; Datatype declarations for parameterized data types: Define Btree: - datatype ('a,'b) Btree = LEAF of 'a NODE of 'b * ('a,'b) Btree * ('a,'b) Btree; datatype ('a,'b) Btree = LEAF of 'a NODE of 'b * ('a,'b) Btree * ('a,'b) Btree - type intbtree = (int, int) Btree; type intbtree = (int,int) Btree Example Functions and their Type 41 / 63 - fun leftmost(leaf(x)) = x = leftmost(node(y, l, r)) = leftmost(l); val leftmost = fn : ('a,'b) Btree -> 'a - fun discriminants(leaf(x)) = nil = discriminants(node(y, l, r)) = = let = val l1 = discriminants(l) = val l2 = discriminants(r) = in = l1 @ (y::l2) (* â œ@â is list concatenation operator *) = end; val discriminants = fn : ('a,'b) Btree -> 'b list 42 / 63

Example Functions (Contd.) - fun append(x::xs, y) = x::append(xs, y) = append(nil, y) = y; val append = fn : 'a list * 'a list -> 'a list - fun f(x::xs, y) = x::f(xs, y) = f(nil, y) = nil; val f = fn : 'a list * 'b -> 'a list SML Operators that restrict polymorphism: Arithmetic, relational, boolean, string, type conversion operators SML Operators that allow polymorphism tuple, projection, list, equality (= and <>) Exceptions 43 / 63 Total function: function is defined for every argument value. Examples: +, length, etc. Partial function: function is defined only for a subset of argument values. Examples: /, Lists.hd, etc. Another example: (* find the last element in a list *) let rec last = function x::[] -> x _::xs -> last xs;; Exceptions can be used to signal invalid arguments. Failed pattern matching (due to incomplete matches) is signalled with (predefined) Match_failure exception. Exceptions also signal unexpected conditions (e.g. I/O errors) 44 / 63 Exceptions (Contd.) Users can define their own exceptions. Exceptions can be thrown using raise (* Exception to signal no elements in a list *) exception NoElements;; let rec last = function [] -> raise NoElements x::[] -> x _::xs -> last xs;; 45 / 63

Exceptions (Contd.) Exceptions can be handled using try... with. exception DumbCall;; let test l y = try (last l) / y with NoElements -> 0 Division_by_zero -> raise DumbCall;; 46 / 63 Higher Order Functions Functions that take other functions as arguments, or return newly constructed functions fun map f nil = nil map f x::xs=(f x)::(map f xs); Map applies a function to every element of a list fun filter f nil = nil filter f x::xs= if (f x) then x::(filter f xs) else (filter f xs) 47 / 63 Higher Order Functions (Contd.) fun zip f nil nil = nil zip f (x::xs) (y::ys)=f(x,y)::(zip f xs ys); fun reduce f b nil = b reduce f b x::xs = f(x, (reduce f b xs)); 48 / 63

Examples of Higher Order Functions Add 1 to every element in list: let rec add_one = function [] -> [] x::xs -> (x+1)::(add_one xs);; Multiply every element in list by 2: let rec double = function [] -> [] x::xs -> (x*2)::(double xs);; Examples of Higher Order Functions (Cont.d) 49 / 63 Perform function f on every element in list: let rec map f = function [] -> [] x::xs -> (f x)::(map f xs);; Now we can write add_one and double as: let add_one = map ((+) 1);; let double = map (( * ) 2);; More Examples 50 / 63 Sum all elements in a list let rec sumlist = function [] -> 0 x::xs -> x + sumlist xs;; Accumulate over a list: Multiply all elements in a list let rec prodlist = function [] -> 1 x::xs -> x * prodlist xs;; let rec foldr f b = function (* f is the function to apply at element; b is the base case value *) [] -> b x::xs -> f x (foldr f b xs);; 51 / 63

More Examples (Contd.) Using foldr: Sum all elements in a list Multiply all elements in a list let sumlist = foldr (+) 0;; let prodlist = foldr ( * ) 1;; Anonymous Functions 52 / 63 You can define an unnamed function -((fn x => 2*x) 5); val it=10 : int Is handy with higher order functions 53 / 63 Section 5 Overview 54 / 63

Summary OCAML definitions have the following syntax: def ::= let [rec] letlhs = expr (value definitions) type typelhs = typeexpr (type definitions) exception definitions... letlhs ::= id [{ pattern }] (patterns specify parameters ) typelhs ::= [{ typevar }] id (typevars specify parameters ) OCAML programs are a sequence of definitions separated by ;; Summary 55 / 63 OCAML expressions have the following syntax: expr ::= const (constants) id (value identifiers) expr op expr (expressions with binary operators) expr expr (function application) let [rec] { letlhs = expr ;;}in expr (let definitions) raise expr (throw exception) Summary (Contd.) 56 / 63 match expr with case [{ case }] (pattern matching) fun case (function definition) function case [{ case }] (function definition with pattern matching) try expr with case [{ case }] (exception handling) case ::= pattern -> expr (pattern matching case) 57 / 63

Section 6 OCAML Performance Writing Efficient OCAML Programs 58 / 63 Using recursion to sum all elements in a list: OCAML let rec sumlist = function [] -> 0 x::xs -> x + sumlist xs;; C int sumlist(list l) { if (l == NULL) else } Iteratively summing all elements in a list (C): int acc = 0; for(l=list; l!=null; l = l->next) return 0; return (l->element) + sumlist(l->next); acc += l->element; 59 / 63 Writing Efficient OCAML Programs (Contd.) Recursive summation takes stack space proportional to the length of the list sumlist([]) sumlist([2]) sumlist([2]) sumlist([1;2]) = sumlist([1;2]) = sumlist([1;2]) 0 2 sumlist([2]) 3 = sumlist([1;2]) = sumlist([1;2]) Iterative summation takes constant stack space. 60 / 63

Tail Recursion let rec last = function [] -> raise NoElements x::[] -> x _::xs -> last xs;; Evaluation of last [1;2;3];; last([3]) last([2;3]) last([2;3]) last([1;2;3]) = last([1;2;3]) = last([1;2;3]) 3 3 = last([1;2;3]) Tail Recursion (Contd.) = 3 last([2;3]) last([1;2;3]) 61 / 63 let rec last = function [] -> raise NoElements x::[] -> x _::xs -> last xs;; Note that when the 3rd pattern matches, the result of last is whatever is the result of last xs. Such calls are known as tail recursive calls. Tail recursive calls can be evaluated without extra stack: last([1;2;3]) = last([2;3]) = last([3]) Taking Efficiency by the Tail 3 62 / 63 An efficient recursive function for summing all elements: C OCAML int acc_sumlist(int acc, List l) { if (l == NULL) return acc; else return acc_sumlist( acc + (l->element), l->next);} int sumlist(list l) { return acc_sumlist(0, l);} let rec acc_sumlist acc = function [] -> acc x::xs -> acc_sumlist (acc+x) xs;; let sumlist l = acc_sumlist 0 l;; acc_sumlist(0,[1;2]) acc_sumlist(1,[2]) acc_sumlist(3,[]) 3 63 / 63