61A LECTURE 22 TAIL CALLS, ITERATORS. Steven Tang and Eric Tzeng July 30, 2013

Similar documents
CS61A Lecture 36. Soumya Basu UC Berkeley April 15, 2013

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

SCHEME AND CALCULATOR 5b

TAIL CALLS, ITERATORS, AND GENERATORS 11

ITERATORS AND STREAMS 9

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

INTERPRETERS 8. 1 Calculator COMPUTER SCIENCE 61A. November 3, 2016

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))

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

61A LECTURE 8 SEQUENCES, ITERABLES

61A LECTURE 8 SEQUENCES, ITERABLES. Steven Tang and Eric Tzeng July 8, 2013

TAIL RECURSION, SCOPE, AND PROJECT 4 11

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

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

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

61A LECTURE 25 DECLARATIVE PROGRAMMING

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

An introduction to Scheme

61A LECTURE 17 ORDERS OF GROWTH, EXCEPTIONS. Steven Tang and Eric Tzeng July 23, 2013

CS450 - Structure of Higher Level Languages

Functional Programming. Pure Functional Languages

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

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

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

Functional Programming. Pure Functional Languages

INTERPRETERS AND TAIL CALLS 9

(Func&onal (Programming (in (Scheme)))) Jianguo Lu

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

Why do we need an interpreter? SICP Interpretation part 1. Role of each part of the interpreter. 1. Arithmetic calculator.

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

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

Announcements. The current topic: Scheme. Review: BST functions. Review: Representing trees in Scheme. Reminder: Lab 2 is due on Monday at 10:30 am.

61A LECTURE 18 SCHEME. Steven Tang and Eric Tzeng July 24, 2013

Func%onal Programming in Scheme and Lisp

User-defined Functions. Conditional Expressions in Scheme

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

Func%onal Programming in Scheme and Lisp

61A LECTURE 15 MEMOIZATION, RECURSIVE DATA, SETS

Overview. Iteration via Tail Recursion in Racket. Factorial Revisited. An itera*ve approach to factorial. What is itera*on?

61A Lecture 32. Wednesday, November 14

Principles of Programming Languages Topic: Functional Programming Professor L. Thorne McCarty Spring 2003

Introduction to Functional Programming

CSCC24 Functional Programming Scheme Part 2

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

Overview. Factorial Revisited. Iteration via Tail Recursion in Racket. An itera*ve approach to factorial. What is itera*on?

61A LECTURE 1 FUNCTIONS, VALUES. Steven Tang and Eric Tzeng June 24, 2013

COMPUTER SCIENCE IN THE NEWS. CS61A Lecture 21 Scheme TODAY REVIEW: DISPATCH DICTIONARIES DISPATCH DICTIONARIES 7/27/2012

CS 314 Principles of Programming Languages. Lecture 16

6.037 Lecture 7B. Scheme Variants Normal Order Lazy Evaluation Streams

Advanced topics, part 2

Overview. Iteration via Tail Recursion in Racket SOLUTIONS. Factorial Revisited. An itera*ve approach to factorial

CS 1110: Introduction to Computing Using Python Loop Invariants

Functional Programming. Pure Functional Programming

Documentation for LISP in BASIC

RECURSION: n. SEE RECURSION 3

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

Streams and Evalutation Strategies

An Explicit-Continuation Metacircular Evaluator

ITERATORS AND GENERATORS 10

Structure and Interpretation of Computer Programs

Fall Semester, The Metacircular Evaluator. Today we shift perspective from that of a user of computer langugaes to that of a designer of

STREAMS 10. Basics of Streams. Practice with Streams COMPUTER SCIENCE 61AS. 1. What is a stream? 2. How does memoization work?

CS 61A Discussion 8: Scheme. March 23, 2017

Sample Final Exam Questions

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

COMPUTER SCIENCE IN THE NEWS. CS61A Lecture 24 Infinite Sequences LAZY EVALUATION AGENDA 8/7/2012. Jom Magrotker UC Berkeley EECS July 30, 2012

Iterators & Generators

CSC324 Functional Programming Efficiency Issues, Parameter Lists

CS61A Lecture 24 Infinite Sequences. Jom Magrotker UC Berkeley EECS July 30, 2012

Structure and Interpretation of Computer Programs

Lecture #13: Type Inference and Unification. Typing In the Language ML. Type Inference. Doing Type Inference

Organization of Programming Languages CS3200/5200N. Lecture 11

Lisp. Versions of LISP

6.184 Lecture 4. Interpretation. Tweaked by Ben Vandiver Compiled by Mike Phillips Original material by Eric Grimson

Chapter 1. Fundamentals of Higher Order Programming

Structure and Interpretation of Computer Programs

Lecture #24: Programming Languages and Programs

An Explicit Continuation Evaluator for Scheme

CS61A Summer 2010 George Wang, Jonathan Kotker, Seshadri Mahalingam, Eric Tzeng, Steven Tang

61A LECTURE 6 RECURSION. Steven Tang and Eric Tzeng July 2, 2013

Local defini1ons. Func1on mul1ples- of

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

Functional Programming - 2. Higher Order Functions

CS251 Programming Languages Spring 2016, Lyn Turbak Department of Computer Science Wellesley College

Lecture #10: Sequences. Last modified: Mon Feb 22 16:33: CS61A: Lecture #10 1

Structure and Interpretation of Computer Programs Spring 2014 Final (with corrections)

Syntactic Sugar: Using the Metacircular Evaluator to Implement the Language You Want

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

A Brief Introduction to Scheme (II)

What is an algorithm?

CS1102: Macros and Recursion

RECURSION, RECURSION, (TREE) RECURSION! 3

Discussion 11. Streams

Problem 1: Binary Trees: Flatten

61A LECTURE 16 TREES, ORDERS OF GROWTH. Steven Tang and Eric Tzeng July 22, 2013

Structure and Interpretation of Computer Programs

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

Repetition Through Recursion

University of Massachusetts Lowell

Fall 2017 December 4, Scheme. Instructions

Transcription:

61A LECTURE 22 TAIL CALLS, ITERATORS Steven Tang and Eric Tzeng July 30, 2013

Announcements Homework 12 due Thursday, not Monday. Take the time to get started on the project instead!

Almost done with Scheme Scheme is a lot simpler than Python, so it has a lot less features than Python does Today we re talking about a feature that Scheme has that Python doesn t!

Iteration Versus Recursion in Python In Python, recursive calls always create new ac4ve frames Time Space def factorial(n): if n == 0: return 1 return n * factorial(n 1) def factorial(n): total = 1 while n > 0: n, total = n 1, total * n return total

Iteration and Recursion Reminder: Iteration is a special case of recursion Idea: The state of iteration can be passed as parameters def factorial(n): total = 1 while n > 0: Local names become n, total = n - 1, total * n return total Parameters in a recursive func4on def factorial(n, total): if n == 0: return total return factorial(n - 1, total * n) But this converted version s4ll uses linear space in Python

Tail Recursion From the Revised 7 Report on the Algorithmic Language Scheme: "Implementa4ons of Scheme are required to be properly tail- recursive. This allows the execu4on of an itera4ve computa4on in constant space, even if the itera4ve computa4on is described by a syntac4cally recursive procedure." (define (factorial n total) (if (= n 0) total (factorial (- n 1) (* total n)))) def factorial(n, total): if n == 0: return total return factorial(n - 1, total * n)

Tail Calls A procedure call that has not yet returned is ac8ve. Some procedure calls are tail calls. A Scheme interpreter should support an unbounded number of ac4ve tail calls. A tail call is a call expression in a tail context: The last body sub- expression in a lambda expression Sub- expressions 2 & 3 in a tail context if expression All non- predicate sub- expressions in a tail context cond The last sub- expression in a tail context and or or The last sub- expression in a tail context begin (define (factorial n total) (if (= n 0) total (factorial (- n 1) (* total n)) ) )

Example: Length of a List (define (length s) (if (null? s) 0 (+ 1 (length (cdr s)) ) ) ) Not a tail context A call expression is not a tail call if more computa4on is s4ll required in the calling procedure. Linear recursions can olen be rewrimen to use tail calls. (define (length-tail s) (define (length-iter s n) (if (null? s) n (length-iter (cdr s) (+ 1 n)) ) ) (length-iter s 0) ) Recursive call is a tail call

Eval with Tail Call Optimization The return value of the tail call is the return value of the current procedure call. Therefore, tail calls shouldn't increase the environment size. In the interpreter, recursive calls to scheme_eval for tail calls must instead be expressed itera4vely.

Logical Special Forms, Revisited Logical forms may only evaluate some sub- expressions. If expression: (if <predicate> <consequent> <alternative>) And and or: (and <e1>... <en>), (or <e1>... <en>) Cond expr'n: (cond (<p1> <e1>)... (<pn> <en>) (else <e>)) The value of an if expression is the value of a sub- expression. Evaluate the predicate. Choose a sub- expression: <consequent> or <alternative> Evaluate that sub- expression in place of the whole expression. Evalua4on of the tail context does not require a recursive call. E.g., replace (if false 1 (+ 2 3)) with (+ 2 3) and iterate. do_if_form scheme_eval

Example: Reduce (define (reduce procedure s start) (if (null? s) start (reduce procedure (cdr s) (procedure start (car s)) ) ) ) Recursive call is a tail call. Other calls are not; constant space depends on procedure. (reduce * '(3 4 5) 2) 120 (reduce (lambda (x y) (cons y x)) '(3 4 5) '(2)) (5 4 3 2)

Example: Map (define (map procedure s) (define (map-iter procedure s m) (if (null? s) m (map-iter procedure (cdr s) (cons (procedure (car s)) m)))) (reverse (map-iter procedure s nil))) (define (reverse s) (define (reverse-iter s r) (if (null? s) r (reverse-iter (cdr s) (cons (car s) r)))) (reverse-iter s nil))

Break! Remember this guy? Guido on tail call optimization: Personally, I think it is a fine feature for some languages, but I don't think it fits Python Why do you think this is? Guido van Rossum Benevolent Dictator for Life

Our Sequence Abstraction Recall our previous sequence interface: A sequence has a finite, known length A sequence allows element selec4on for any element In the cases we ve seen so far, sa4sfying the sequence interface requires storing the en4re sequence in a computer's memory Problems? Infinite sequences - primes, posi4ve integers Really large sequences - all TwiMer tweets, votes in a presiden4al elec4on

The Sequence of Primes Think about the sequence of prime numbers: What s the first one? The next one? The next one? How about the next two? How about the 105 th prime? Our sequence abstrac4on would give an instant answer

Implicit Sequences We compute each of the elements on demand Don t explicitly store each element Called an implicit sequence

A Python Example Example: The range class represents a regular sequence of integers The range is represented by three values: start, end, and step The length and elements are computed on demand Constant space for arbitrarily long sequences

A Range Class class Range(object): def init (self, start, end=none, step=1): if end is None: start, end = 0, start self.start = start self.end = end self.step = step def len (self): return max(0, ceil((self.end - self.start) / self.step)) def getitem (self, k): if k < 0: k = len(self) + k if k < 0 or k >= len(self): raise IndexError('index out of range') return self.start + k * self.step

The Iterator Interface An iterator is an object that can provide the next element of a (possibly implicit) sequence The iterator interface has two methods: iter (self) returns an equivalent iterator next (self) returns the next element in the sequence If no next, raises StopIteration excep4on There are also built in func4ons next and iter that call the corresponding method on their argument.

RangeIter class RangeIter(object): def init (self, start, end, step): self.current = start self.end = end self.step = step self.sign = 1 if step > 0 else -1 def next (self): if self.current * self.sign >= self.end * self.sign: raise StopIteration result = self.current self.current += self.step return result def iter (self): return self

Fibonacci class FibIter(object): def init (self): self.prev = -1 self.current = 1 def next (self): self.prev, self.current = (self.current, self.prev + self.current) return self.current def iter (self): return self

The For Statement for <name> in <expression>: <suite> 1. Evaluate the header <expression>, which yields an iterable object. 2. For each element in that sequence, in order: A. Bind <name> to that element in the first frame of the current environment B. Execute the <suite> An iterable object has a method iter that returns an iterator >>> nums, sum = [1, 2, 3], 0 >>> for item in nums: sum += item >>> sum 6 >>> nums, sum = [1, 2, 3], 0 >>> items = nums. iter () >>> try: while True: item = items. next () sum += item except StopIteration: pass >>> sum 6