Lets and Loops Tail Recursion.

Slides:



Advertisements
Similar presentations
Higher-Order Functions and Loops c. Kathi Fisler,
Advertisements

More about functions Plus a few random things. 2 Tail recursion A function is said to be tail recursive if the recursive call is the very last thing it.
Tail Recursion. Problems with Recursion Recursion is generally favored over iteration in Scheme and many other languages – It’s elegant, minimal, can.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
Lisp II. How EQUAL could be defined (defun equal (x y) ; this is how equal could be defined (cond ((numberp x) (= x y)) ((atom x) (eq x y)) ((atom y)
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Lisp II. How EQUAL could be defined (defun equal (x y) ; this is how equal could be defined (cond ((numberp x) (= x y)) ((atom x) (eq x y)) ((atom y)
CSE 341 Lecture 16 More Scheme: lists; helpers; let/let*; higher-order functions; lambdas slides created by Marty Stepp
Recursion. Recursion is a powerful technique for thinking about a process It can be used to simulate a loop, or for many other kinds of applications In.
Tail Recursion. Problems with Recursion Recursion is generally favored over iteration in Scheme and many other languages It’s elegant, minimal, can be.
Clojure Template Tail Recursion. Hello, Factorial! The factorial function is everybody’s introduction to recursion (defn factorial-1 [n] (if (zero? n)
Recursion Great fleas have little fleas upon their backs to bite 'em, And little fleas have lesser fleas, and so ad infinitum. And the great fleas themselves,
>(setf oldlist ) Constructing a list We know how to make a list in lisp; we simply write it: ‘4321( ) What if we want a new list with that list as a part?
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Tail Recursion. Problems with Recursion Recursion is generally favored over iteration in Scheme and many other languages – It’s elegant, minimal, can.
Conditionals and Recursion "To iterate is human, to recurse divine." - L. Peter Deutsch.
Clojure 3 Recursion, Higher-order-functions 27-Aug-15.
Solving N-Queens in Clojure
Clojure 4 Sequences 20-Oct-15. Clojure errors (NO_SOURCE_FILE:12) Useless--just means you’re running from the REPL shell java.lang.Exception: EOF while.
Clojure 2 Feb 7,
Feb 7, 2015 Thinking in Clojure. Jumping in We’ll quickly go through Clojure’s data types, some basic functions, and basic syntax Then we’ll get to the.
Function Design in LISP. Program Files n LISP programs are plain text –DOS extensions vary; use.lsp for this course n (load “filename.lsp”) n Can use.
Solving Your Problem by Generalization CS 5010 Program Design Paradigms “Bootcamp” Lesson © Mitchell Wand, This work is licensed under.
Fall 2016 Images from Sebesta: Copyright © 2012 Addison-Wesley. All rights reserved. The mind is everything. What you think you become. Buddha.
Fall 2016 Images from Sebesta: Copyright © 2012 Addison-Wesley. All rights reserved.
Recursion Great fleas have little fleas upon their backs to bite 'em, And little fleas have lesser fleas, and so ad infinitum. And the great fleas themselves,
Programming with Recursion
List Algorithms Taken from notes by Dr. Neil Moore & Dr. Debby Keen
Tail Recursion.
CS 550 Programming Languages Jeremy Johnson
More About Recursive Data Types
Class 11: Two-argument recursion
PPL Lazy Lists.
More Recursive Data Types
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2017.
Closures and Streams cs784(Prasad) L11Clos
CS 270 Math Foundations of CS Jeremy Johnson
Recursion Great fleas have little fleas upon their backs to bite 'em, And little fleas have lesser fleas, and so ad infinitum. And the great fleas themselves,
6.001 SICP Data abstractions
Important Concepts from Clojure
Important Concepts from Clojure
List Algorithms Taken from notes by Dr. Neil Moore
Clojure 4 Sequences 27-Nov-18.
The Metacircular Evaluator
Clojure 4 Sequences 5-Dec-18.
Solving Your Problem by Generalization
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2013.
The Metacircular Evaluator
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Autumn 2018.
The Metacircular Evaluator (Continued)
Madhusudan Parthasarathy
Recursion Great fleas have little fleas upon their backs to bite 'em, And little fleas have lesser fleas, and so ad infinitum. And the great fleas themselves,
Recursion Great fleas have little fleas upon their backs to bite 'em, And little fleas have lesser fleas, and so ad infinitum. And the great fleas themselves,
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Zach Tatlock Winter 2018.
Recursion, Higher-order-functions
Announcements Quiz 5 HW6 due October 23
For loops Taken from notes by Dr. Neil Moore
List and list operations (continue).
Important Concepts from Clojure
Abstraction and Repetition
Yan Shi CS/SE 2630 Lecture Notes
Clojure 2 22-Apr-19.
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2016.
Developing Programs for Family Trees
Clojure 3 1-Jun-19.
Thinking in Clojure 8-Jun-19.
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2019.
More Scheme CS 331.
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Autumn 2017.
Presentation transcript:

Lets and Loops Tail Recursion

Hello, Factorial! The factorial function is everybody’s introduction to recursion (defn factorial-1 [n] (if (zero? n) 1 (* n (factorial-1 (dec n))))) (factorial-1 10) ;=> 3628800 The problem with this function is that every recurrence increases the stack size Not a problem if the number of recurrences is small

Tail recursion, or tail call recursion A function is tail recursive if, for every recursive call in the function, the recursive call is the last thing done in the function In this situation, the compiler can replace the recursion with a simple loop, which does not add frames to the stack The programmer still does not have (or need!) loops In factorial-1, (* n (factorial-1 (dec n))) the multiplication keeps it from being tail recursive To make the factorial function tail recursive, we need to somehow bring the multiplication into the parameter list

Adding an accumulator (defn factorial-two-args [acc n] (if (zero? n) acc (recur (* acc n) (dec n)))) One way to think of this is as “pumping” information from the input parameter to the accumulator

Using factorial-two-args (factorial-helper 1 10) ;=> 3628800 (factorial-helper 0 10) ;=> 0 (factorial-helper 10 1) ;=> 10

Use of a faҫade We can use a façade along with the “real” function (now called “factorial-helper” (defn factorial-2 [n] (factorial-helper 1 n)) (defn factorial-helper [acc n] (if (zero? n) acc (recur (* acc n) (dec n)))) This adds an unnecessary function to those available to the user

When tail recursion isn’t The function (defn factorial-? [acc n] (if (zero? n) acc (factorial-? (* acc n) (dec n)))) is tail recursive, but that doesn’t do you any good unless you tell the compiler to replace the recursion with a loop Use recur instead of factorial-? in the tail call

Polymorphic parameters Clojure functions can be defined with more than one parameter list (defn factorial-3 ([n] (factorial-3 1 n)) ([acc n] (if (zero? n) acc (recur (* acc n) (dec n)) ) ) )

Defining a local helper function (defn factorial-4 [number] (let [factorial-helper (fn [acc n] (if (zero? n) acc (recur (* acc n) (dec n))))] (factorial-helper 1 number)))

let and loop In the previous example, we used (let [factorial-helper (fn [acc n] …]…) to define a helper function with local scope The general form is (let [name1 value1, …, nameN valueN] code) and we use recur in the code to tell the compiler to turn this into a loop To simplify this, Clojure provides a loop construct: (loop [name1 value1, …, nameN valueN] code) This is not a loop; it’s a request to the compiler to turn tail recursion into a loop! The name/value pairs are initial values of parameters The call to recur in the body supplies new values for the parameters

let and loop comparison (defn factorial-4 [number] (let [factorial-helper (fn [acc n] (if (zero? n) acc (recur (* acc n) (dec n))))] (factorial-helper 1 number))) (defn factorial-5 [number] (loop [acc 1, n number] (if (zero? n) acc (recur (* acc n) (dec n)))))

shallow-reverse (defn shallow-reverse-1 ([lst] (shallow-reverse () lst)) ([acc lst] (if (empty? lst) acc (recur (cons (first lst) acc) (rest lst)) ) ) ) (defn shallow-reverse-2 [lst] (loop [acc (), lst-2 lst] (if (empty? lst-2) acc (recur (cons (first lst-2) acc) (rest lst-2)) ) ) )

find-first-index Problem: Find the index of the first thing in a sequence that satisfies a given predicate (defn find-first-index [pred a-seq] (loop [acc 0, b-seq a-seq] (cond (empty? b-seq) nil (pred (first b-seq)) acc :else (recur (inc acc) (rest b-seq)) ) ) )

Find the average of a sequence (defn avg [a-seq] (loop [sum 0, n 0, b-seq a-seq] (if (empty? b-seq) (/ sum n) (recur (+ sum (first b-seq)) (inc n) (rest b-seq)) ) ) ) Notice that the loop takes 3 arguments

Summary: Tail recursion Tail recursion saves stack space, but the code is somewhat harder to read When the recursion is guaranteed to be “not too deep,” you can ignore tail recursion Tail recursion isn’t too hard, as long as you remember the “bucket” analogy …and don’t forget to use recur!

The End