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

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

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

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

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

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

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

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

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

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

ITERATORS AND STREAMS 9

SCHEME AND CALCULATOR 5b

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

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

An introduction to Scheme

TAIL CALLS, ITERATORS, AND GENERATORS 11

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

CS450 - Structure of Higher Level Languages

INTERPRETERS AND TAIL CALLS 9

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

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

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

Introduction to Functional Programming

Streams and Evalutation Strategies

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

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

Functional Programming

Lisp. Versions of LISP

Functional Programming. Pure Functional Programming

TAIL RECURSION, SCOPE, AND PROJECT 4 11

A Brief Introduction to Scheme (II)

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

Building a system for symbolic differentiation

Problem Set 4: Streams and Lazy Evaluation

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

Functional Programming. Pure Functional Languages

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

Sample midterm 1 #1. Problem 1 (What will Scheme print?).

Functional Programming. Pure Functional Languages

Modern Programming Languages. Lecture LISP Programming Language An Introduction

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

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

An Explicit Continuation Evaluator for Scheme

Building a system for symbolic differentiation

STREAMS 10. Basics of Streams. Practice with Streams COMPUTER SCIENCE 61AS. 1. What is a stream?

Structure and Interpretation of Computer Programs

Structure and Interpretation of Computer Programs

Fall 2017 December 4, Scheme. Instructions

University of Massachusetts Lowell

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

The University of Nottingham

CS61A Midterm 2 Review (v1.1)

Discussion 4. Data Abstraction and Sequences

Fall 2017 December 4, 2017

Structure and Interpretation of Computer Programs

An Explicit-Continuation Metacircular Evaluator

ENVIRONMENT DIAGRAMS AND RECURSION 2

Scheme Basics > (butfirst '(help!)) ()

Structure and Interpretation of Computer Programs

Sample Final Exam Questions

Lecture #24: Programming Languages and Programs

Notes on Higher Order Programming in Scheme. by Alexander Stepanov

Principles of Programming Languages

Scheme Tutorial. Introduction. The Structure of Scheme Programs. Syntax

Lisp Basic Example Test Questions

PAIRS AND LISTS 6. GEORGE WANG Department of Electrical Engineering and Computer Sciences University of California, Berkeley

Introduction to Scheme

This exam is worth 70 points, or about 23% of your total course grade. The exam contains 15 questions.

CS61A Notes Disc 11: Streams Streaming Along

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

regsim.scm ~/umb/cs450/ch5.base/ 1 11/11/13

April 2 to April 4, 2018

Organization of Programming Languages CS3200/5200N. Lecture 11

Discussion 11. Streams

CS61A Notes 02b Fake Plastic Trees. 2. (cons ((1 a) (2 o)) (3 g)) 3. (list ((1 a) (2 o)) (3 g)) 4. (append ((1 a) (2 o)) (3 g))

Programming Languages

JVM ByteCode Interpreter

CSCI0170. Today s topics. Predicates Natural Number recursion Recursion Diagrams List recursion A first glance at the design recipe

CSCC24 Functional Programming Scheme Part 2

Design and Analysis of Algorithms Prof. Madhavan Mukund Chennai Mathematical Institute. Module 02 Lecture - 45 Memoization

A LISP Interpreter in ML

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

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

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

Typed Scheme: Scheme with Static Types

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

YOUR NAME PLEASE: *** SOLUTIONS ***

Repetition Through Recursion

Structure and Interpretation of Computer Programs

Scheme. Functional Programming. Lambda Calculus. CSC 4101: Programming Languages 1. Textbook, Sections , 13.7


Documentation for LISP in BASIC

Functional Programming Languages (FPL)

Homework 1. Notes. What To Turn In. Unix Accounts. Reading. Handout 3 CSCI 334: Spring, 2017

Chapter 1. Fundamentals of Higher Order Programming

An Introduction to Scheme

INTERPRETATION AND SCHEME LISTS 12

Lecture Notes on Lisp A Brief Introduction

CSE413 Midterm. Question Max Points Total 100

Chapter 15. Functional Programming Languages

4.2 Variations on a Scheme -- Lazy Evaluation

Transcription:

SCHEME 0 COMPUTER SCIENCE 6A July 26, 206 0. Warm Up: Conditional Expressions. What does Scheme print? scm> (if (or #t (/ 0 (/ 0 scm> (if (> 4 3 (+ 2 3 4 (+ 3 4 (* 3 2 scm> ((if (< 4 3 + - 4 00 scm> (if 0 2 0.2 Warm Up: Write Some Functions. Write a function that calculates factorial. (Note we have not seen any iteration yet. (define (factorial x

DISCUSSION 0: SCHEME Page 2 2. Write a function that calculates the n th Fibonacci number. (define (fib n (if (< n 2 Pairs and Lists To construct a (linked list in Scheme, you can use the constructor cons (which takes two arguments. nil represents the empty list. If you have a linked list in Scheme, you can use selector car to get the first element and selector cdr to get the rest of the list. (car and cdr don t stand for anything anymore, but if you want the history go to http://en.wikipedia.org/wiki/car_and_cdr. scm> nil ( scm> (null? nil #t scm> (cons 2 nil (2 scm> (cons 3 (cons 2 nil (3 2 scm> (define a (cons 3 (cons 2 nil a scm> (car a 3 scm> (cdr a (2 scm> (car (cdr a 2 scm> (define (len a (if (null? a 0 (+ (len (cdr a len scm> (len a 2

DISCUSSION 0: SCHEME Page 3 If a list is a good looking list, like the ones above where the second element is always a linked list, we call it a well-formed list. Interestingly, in Scheme, the second element does not have to be a linked list. You can give something else instead, but cons always takes exactly 2 arguments. These lists are called malformed list. The difference is a dot: scm> (cons 2 3 (2. 3 scm> (cons 2 (cons 3 nil (2 3 scm> (cdr (cons 2 3 3 scm> (cdr (cons 2 (cons 3 nil (3 In general, the rule for displaying a pair is as follows: use the dot to separate the car and cdr fields of a pair, but if the dot is immediately followed by an open parenthesis, then remove the dot and the parenthesis pair. Thus, (0. (. 2 becomes (0. 2 There are many useful operations and shorthands on lists. One of them is list special form list takes zero or more arguments and returns a list of its arguments. Each argument is in the car field of each list element. It behaves the same as quoting a list, which also creates the list. scm> (list 2 3 ( 2 3 scm> '( 2 3 ( 2 3 scm> (car '( 2 3 scm> (equal? '( 2 3 (list 2 3 #t scm> '(. (2 3 ( 2 3 scm> '(define (square x (* x x (define (square x (* x x

DISCUSSION 0: SCHEME Page 4. Define a function that takes 2 lists and concatenates them together. Notice that simply calling (cons a b would not work because it will create a deep list. Instead, think recursively! (define (concat a b scm> (concat '( 2 3 '(2 3 4 ( 2 3 2 3 4 2. Define replicate, which takes an element x and a non-negative integer n, and returns a list with x repeated n times. (define (replicate x n scm> (replicate 5 3 (5 5 5

DISCUSSION 0: SCHEME Page 5 3. A run-length encoding is a method of compressing a sequence of letters. The list (a a a b a a a a can be compressed to ((a 3 (b (a 4, where the compressed version of the sequence keeps track of how many letters appear consecutively. Write a Scheme function that takes a compressed sequence and expands it into the original sequence. Hint: try to use functions you defined earlier in this worksheet. (define (uncompress s scm> (uncompress '((a (b 2 (c 3 (a b b c c c 2 Streams In Python, we can use iterators to represent infinite sequences. However, Scheme does not support iterators. Let s see what happens when we try to use a Scheme list to represent an infinite sequence of natural numbers: scm> (define (naturals n (cons n (naturals (+ n naturals scm> (naturals 0 Error: maximum recursion depth exceeded Because the second argument to cons is always evaluated, we cannot create an infinite sequence of integers using a Scheme list. Instead, our Scheme interpreter (and scheme.cs6a.org supports streams, which are lazy Scheme lists. The first element is represented explicitly, but the rest of the stream s elements are computed only when needed. This evaluation strategy, where we don t compute a value until it is needed, is called lazy evalutation. Let s try to implement the sequence of natural numbers again using a stream!

DISCUSSION 0: SCHEME Page 6 scm> (define (naturals n (cons-stream n (naturals (+ n naturals scm> (define nat (naturals 0 nat scm> (car nat 0 scm> (car (cdr-stream nat scm> (car (cdr-stream (cdr-stream nat 2 We use the special form cons-stream to create a stream. Note that cons-stream is a special form, because the second operand (naturals (+ n is not evaluated when cons-stream is called. It s only evaluated when cdr-stream is used to inspect the rest of the stream. nil is the empty stream cons-stream creates a non-empty stream from an initial element and an expression to compute the rest of the stream car returns the first element of the stream cdr-stream computes and returns the rest of stream Streams are very similar to Scheme lists. The cdr of a Scheme list is either another Scheme list or nil; likewise, the cdr-stream of a stream is either a stream or nil. The difference is that the expression for the rest of the stream is computed the first time that cdr-stream is called, instead of when cons-stream is used. Subsequent calls to cdr-stream return this value without recomputing it. This allows us to efficiently work with infinite streams like the naturals example above. We can see this in action by using a non-pure function to compute the rest of the stream: scm> (define (compute-rest n...> (print 'evaluating!...> (cons-stream n nil compute-rest scm> (define s (cons-stream 0 (compute-rest s scm> (car (cdr-stream s evaluating! scm> (car (cdr-stream s

DISCUSSION 0: SCHEME Page 7 Note that the symbol evaluating! is only printed the first time cdr-stream is called, and no other time.. Write map-stream, which takes a function f and a stream s and returns a new stream, which has all the elements from s, but with f applied to each one. (define (map-stream f s scm> (define evens (map-stream (lambda (x (* x 2 nat evens scm> (car (cdr-stream evens 2 2. The Fibonacci sequence is a classic infinite sequence. Implement make-fib-stream, which takes two numbers and produces a stream of Fibonacci numbers starting with those two numbers. (define (make-fib-stream a b scm> (define fib-stream (make-fib-stream 0 fib-stream scm> (car (cdr-stream (cdr-stream (cdr-stream (cdr-stream (cdr-stream fib-stream 5

DISCUSSION 0: SCHEME Page 8 3 Tail-Call Optimization Scheme implements tail-call optimization, which allows programmers to write recursive functions that use a constant amount of space. A tail call occurs when a function calls another function as its last action of the current frame. Because in this case Scheme won t make any further variable lookups in the frame, the frame is no longer needed, and we can remove it from memory. In other words, if this is the last thing you are going to do in a function call, we can reuse the current frame instead of making a new frame. Consider this version of factorial that does not use tail calls: (define (fact n (if (= n 0 (* n (fact (- n The recursive call occurs in the last line, but it is not the last expression evaluated. After calling (fact (- n, the function still needs to multiply that result with n. The final expression that is evaluated is a call to the multiplication function, not fact itself. Therefore, the recursive call is not a tail call. However, we can rewrite this function using a helper function that remembers the temporary product that we have calculated so far in each recursive step. (define (fact n (define (fact-tail n result (if (= n 0 result (fact-tail (- n (* n result (fact-tail n fact-tail makes a single recursive call to fact-tail that is the last expression to be evaluated, so it is a tail call. Therefore, fact-tail is a tail recursive process. Tail recursive processes can take a constant amount of memory because each recursive call frame does not need to be saved. Our original implementation of fact required the program to keep each frame open because the last expression multiplies the recursive result with n. Therefore, at each frame, we need to remember the current value of n. In contrast, the tail recursive fact-tail does not require the interpreter to remember the values for n or result in each frame. Instead, we can just update the value of n and result of the current frame! Therefore, we can carry out the calculation using only enough memory for a single frame. 3. Identifying tail calls A function call is a tail call if it is in a tail context (but a tail call might not be a recursive tail call as seen above in the first fact definition. We consider the following to be tail contexts:

DISCUSSION 0: SCHEME Page 9 the last sub-expression in a lambda s body the second or third sub-expression in an if form any of the non-predicate sub-expressions in a cond form the last sub-expression in an and or an or form the last sub-expression in a begin s body Before we jump into questions, a quick tip for defining tail recursive functions is to use helper functions. A helper function should have all the arguments from the parent function, plus additional arguments like total or counter or result.. For each of the following functions, identify whether it contains a recursive call in a tail context. Also indicate if it uses a constant number of frames. (define (question-a x (if (= x 0 0 (+ x (question-a (- x (define (question-b x y (if (= x 0 y (question-b (- x (+ y x (define (question-c x y (if (> x y (question-c (- y x (question-c (+ x 0 y (define (question-d n (if (question-d n (question-d (- n (question-d (+ n 0 2. Write a tail recursive function that returns the nth fibonacci number. We define fib(0 = 0 and fib( =. (define (fib n