1 of 20

CSE 341: Section 3

OCaml Pattern Matching and Tail Recursion

2 of 20

Reminders

  • Homework 2 due tomorrow at 5 pm
  • Midterm on Wednesday, 10/28
    • That’s in less than 2 weeks!!

3 of 20

Agenda

  • Variants & Records
  • Pattern Matching
  • Tail Recursion

4 of 20

Variants & Records

5 of 20

What is the difference?

Records: a new way to build each-of types

  • Named types and named fields
  • Similar to tuples

Variants: a new way to build custom one-of types

  • Named types
  • An enumeration is the simplest version of variants

6 of 20

What variable belongs to which type definition?

  1. ​

b.

c.

7 of 20

What variable belongs to which type definition?

  • Variant

b. Record

c. Variant

8 of 20

Pattern Matching

9 of 20

Why Pattern Match

Used to destruct variants

10 of 20

Why Pattern Match

Also a cleaner representation of different cases/patterns as opposed to if-else branches

11 of 20

Exercise - Problem 2 & 3

Create an appropriate pattern for the given types.

Use pattern matching to implement the remaining functions according to the spec.

12 of 20

Tail Recursion

13 of 20

Making functions tail-recursive

Sometimes we can rewrite our algorithm to be tail-recursive

​

​

​

​

Sometimes we can’t easily/profitably do so:

  • Example: processing a tree (two recursive calls can’t both be tail calls)
  • Example: if order matters in a resulting list

let factorial n =

let rec loop (n,acc) = if n=0 then acc else loop (n-1,acc*n) in

loop (n,1)

let x = factorial 3

14 of 20

Methodology

There is a methodology to guide the transformation to a tail-recursive function:

  • Create a helper function that takes an accumulator
  • Old base case becomes initial accumulator
  • New base case becomes final accumulator

15 of 20

Methodology

  1. Create a helper function that takes an accumulator
  2. Old base case becomes initial accumulator
  3. New base case becomes final accumulator

1

16 of 20

Methodology

  • Create a helper function that takes an accumulator
  • Old base case becomes initial accumulator
  • New base case becomes final accumulator

1

2

17 of 20

Methodology

  • Create a helper function that takes an accumulator
  • Old base case becomes initial accumulator
  • New base case becomes final accumulator

1

2

3

18 of 20

Tail Recursion

type expr =

| Constant of int

| Negate of expr

| Add of expr * expr

| Mul of expr * expr

let rec eval e =

match e with

| Constant i -> i

| Negate e1 -> - (eval e1)

| Add (e1, e2) -> (eval e1) + (eval e2)

| Mul (e1, e2) -> (eval e1) * (eval e2)

Why shouldn't we try to make eval tail-recursive?

​

​

19 of 20

Summary: Tail Recursion

A call that will be the caller’s answer “as is” is called a tail call

A recursive function where all recursive calls are tail calls is called “tail recursive”

20 of 20

Exercise - Problem 3

Use tail recursion to implement the following functions according to the spec.