Similar documents
CS 61A Interpreters, Tail Calls, Macros, Streams, Iterators. Spring 2019 Guerrilla Section 5: April 20, Interpreters.

Introduction to Functional Programming

Box-and-arrow Diagrams

An introduction to Scheme

Tail Recursion and Accumulators

Macros & Streams Spring 2018 Discussion 9: April 11, Macros

SCHEME 10 COMPUTER SCIENCE 61A. July 26, Warm Up: Conditional Expressions. 1. What does Scheme print? scm> (if (or #t (/ 1 0)) 1 (/ 1 0))

PROBLEM SOLVING 11. July 24, 2012

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

CS450 - Structure of Higher Level Languages

LECTURE 16. Functional Programming

CONCEPTS OF PROGRAMMING LANGUAGES Solutions for Mid-Term Examination

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

Streams. CS21b: Structure and Interpretation of Computer Programs Spring Term, 2004

Intro. Scheme Basics. scm> 5 5. scm>

CSE 413 Midterm, May 6, 2011 Sample Solution Page 1 of 8

RACKET BASICS, ORDER OF EVALUATION, RECURSION 1

University of Massachusetts Lowell

Deferred operations. Continuations Structure and Interpretation of Computer Programs. Tail recursion in action.

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

CSc 520 Principles of Programming Languages

Fall 2018 Discussion 8: October 24, 2018 Solutions. 1 Introduction. 2 Primitives

CSE413 Midterm. Question Max Points Total 100

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

CS 360 Programming Languages Interpreters

Procedural abstraction SICP Data abstractions. The universe of procedures forsqrt. Procedural abstraction example: sqrt

CSC 533: Programming Languages. Spring 2015

Racket Pattern Matching

Discussion 4. Data Abstraction and Sequences

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

Using Symbols in Expressions (1) evaluate sub-expressions... Number. ( ) machine code to add

FUNKCIONÁLNÍ A LOGICKÉ PROGRAMOVÁNÍ 3. LISP: ZÁKLADNÍ FUNKCE, POUŽÍVÁNÍ REKURZE,

Lecture 35: Analysis Review & Tail Recursion 10:00 AM, Nov 28, 2018

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

Optimizing Scheme, part I

CPS 506 Comparative Programming Languages. Programming Language Paradigm

CSE 341 Section Handout #6 Cheat Sheet

SCHEME AND CALCULATOR 5b

HIERARCHICAL DATA What is a Tree? How is it different from a Deep List? When would you use one over the other?

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

MORE SCHEME. 1 What Would Scheme Print? COMPUTER SCIENCE MENTORS 61A. October 30 to November 3, Solution: Solutions begin on the following page.

Wellesley College CS251 Programming Languages Spring, 2000 FINAL EXAM REVIEW PROBLEM SOLUTIONS

Functional Programming. Pure Functional Programming

Programming Languages. Function-Closure Idioms. Adapted from Dan Grossman's PL class, U. of Washington

UNIVERSITY OF TORONTO Faculty of Arts and Science. Midterm Sample Solutions CSC324H1 Duration: 50 minutes Instructor(s): David Liu.

Introduction to Scheme

Recursion & Iteration

Administrivia. Simple data types

This should prevent residual sexism, racism, favoritism lurking in the unconscious of your professor & TA from biasing grading!!

Scheme as implemented by Racket

SCHEME The Scheme Interpreter. 2 Primitives COMPUTER SCIENCE 61A. October 29th, 2012

Warm-up! CS 3 Final Review. Predict the output. Predict the Output. Predict the output. Predict the output. What is your favorite color?

Chapter 15. Functional Programming Languages

An Explicit-Continuation Metacircular Evaluator

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

Programming Languages. Streams Wrapup, Memoization, Type Systems, and Some Monty Python

Problem Set 4: Streams and Lazy Evaluation

Interpreters and Tail Calls Fall 2017 Discussion 8: November 1, 2017 Solutions. 1 Calculator. calc> (+ 2 2) 4

From the λ-calculus to Functional Programming Drew McDermott Posted

Fall 2017 December 4, 2017

Fall 2017 December 4, Scheme. Instructions

Forward recursion. CS 321 Programming Languages. Functions calls and the stack. Functions calls and the stack

Functional Languages. Hwansoo Han

Scheme Quick Reference

Discussion 11. Streams

Chapter 1. Fundamentals of Higher Order Programming

Streams and Evalutation Strategies

Problem 1: Binary Trees: Flatten

Reading 8 : Recursion

Example Scheme Function: equal

Recursion. What is Recursion? Simple Example. Repeatedly Reduce the Problem Into Smaller Problems to Solve the Big Problem

Defining Recursive Procedures. Lecture 8: Recursing Lists. list? Tracing list? sumlist. Defining Recursive Procedures on Lists

MORE RECURSIVE FUNCTIONS

Unit #2: Recursion, Induction, and Loop Invariants

CSE341 Autumn 2017, Final Examination December 12, 2017

Debugging in LISP. trace causes a trace to be printed for a function when it is called

An Introduction to Scheme

First-Class Synchronization Barriers. Franklyn Turbak Wellesley College

Functional Programming Languages (FPL)

YOUR NAME PLEASE: *** SOLUTIONS ***

Delayed Expressions Fall 2017 Discussion 9: November 8, Iterables and Iterators. For Loops. Other Iterable Uses

Scheme Quick Reference

CS 415 Midterm Exam Fall 2003

A Brief Introduction to Scheme (II)

Functional Programming. Pure Functional Programming

Programming Languages. Thunks, Laziness, Streams, Memoization. Adapted from Dan Grossman s PL class, U. of Washington

Documentation for LISP in BASIC

Building a system for symbolic differentiation

6.001 SICP. Types. Types compound data. Types simple data. Types. Types procedures

Introduction to Python Programming

CSE413: Programming Languages and Implementation Racket structs Implementing languages with interpreters Implementing closures

Introduction to Functional Programming in Racket. CS 550 Programming Languages Jeremy Johnson

CS61A Notes Disc 11: Streams Streaming Along

Functional Programming. Overview. Topics. Definition n-th Fibonacci Number. Graph

Lecture #24: Programming Languages and Programs

CSE 341, Spring 2011, Final Examination 9 June Please do not turn the page until everyone is ready.

Identify recursive algorithms Write simple recursive algorithms Understand recursive function calling

COMP-202: Foundations of Programming. Lecture 13: Recursion Sandeep Manjanna, Summer 2015

Haskell: From Basic to Advanced. Part 3 A Deeper Look into Laziness

Structure and Interpretation of Computer Programs

Transcription:

https://lambda.mines.edu

1 Recursion is a beautiful way to express many algorithms, as it typically makes our algorithm easier to prove. 2 Calling a function requires space on the call stack for the variables, parameters, and return address from the call. 3 What if we could translate certain kinds of recursion into loops at compile time so that we could use it feasibly?

A tail-call is a function call for which the return value of the call becomes the return value of the function. For example, sqrt is the tail-call of this function: double distance(struct point a, struct point b) { double dx = a.x - b.x; double dy = a.y - b.y; return sqrt(dx * dx + dy * dy); } A function which is tail-recursive only ever calls itself as a tail call.

Consider this Racket function: (define (sqrt x guess) (if (< (abs (- (expt guess 2) x)) 0.001) guess (sqrt x (* 0.5 (+ guess (/ x guess)))))) The only place sqrt ever calls itself is in a tail position if is a macro: it returns something to be evaluated rather than evaluating it itself Since (sqrt x (*...)) is one of the returned forms from if, it is a tail call.

Identify the tail-calls and state whether the function is tail-recursive or not. (define (double-all lst) (if (null? lst) '() (cons (* 2 (car lst)) (double-all (cdr lst)))))

Identify the tail-calls and state whether the function is tail-recursive or not. (define (sum-list lst) (if (null? lst) 0 (+ (car lst) (sum (cdr lst)))))

Identify the tail-calls and state whether the function is tail-recursive or not. (define (sum-list lst) (define (sum-iter lst acc) (if (null? lst) acc (sum-iter (cdr lst) (+ (car lst) acc)))) (sum-iter lst 0))

Identify the tail-calls and state whether the function is tail-recursive or not. (define (fib n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))

Identify the tail-calls and state whether the function is tail-recursive or not. (define (fib n) (define (fib-iter n a b) (if (= n 0) a (fib-iter (- n 1) b (+ a b)))) (fib-iter n 0 1))

To translate a tail recursive function to a loop, we can surround the function body in an infinite loop, and when we tail-call ourselves, replace that with a reassignment of our arguments and a continue. How might this look in the code below? int fib_iter(int n, int a, int b) { if (n == 0) return n; return fib_iter(n - 1, a, b); }

Before optimization: int fib_iter(int n, int a, int b) { if (n == 0) return n; return fib_iter(n - 1, a, b); } After optimization: (not pretty, but shows what a compiler might do) int fib_iter(int n, int a, int b) { while (true) { if (n == 0) return n; int next_n = n - 1, next_a = b, next_b = a + b; n = next_n, a = next_a, b = next_b; continue; } }

What if we wanted our compiler to handle circular recursive cases like this: 1 Procedure A can tail-call procedure B. 2 Procedure B can tail-call procedure C. 3 Procedure C can tail-call procedure A. Brainstorm optimization techniques with your learning group. Think aloud!

Idea: in interpreted languages, we have an evaluator function which takes an expression and the storage context, if we make this function call functions in a loop and have our functions return what it should call next, we can get free tail-call optimization that also supports circular tail calls! (figure on whiteboard)

Figure: Think of these people as functions, one function returns its unevaluated tail-call to the trampoine rather than calling it itself.

The only structure for looping in SlytherLisp is recursion, so we need to be able to efficiently be able to implement loops in SlytherLisp. You should implement TCO using the trampoline method. Hint: lisp_eval can be your trampoline.

Some tail call optimizers have an additional trick in their hat: tail call modulo cons. This technique allows the CDR argument to a cons tail call to become a tail call. 1 Rather than waiting for the CDR to finish evaluating to construct the cons cell, the cell is constructed right away without setting the CDR argument. 2 A reference to the CDR is passed back to the trampoline. 3 The trampoline stores the result of the CDR evaluation into the CDR reference. The Racket compiler implements this technique. You are not required to implement this in SlytherLisp.