CSE 341 Lecture 20 Mutation; memoization slides created by Marty Stepp

Slides:



Advertisements
Similar presentations
Modern Programming Languages, 2nd ed.
Advertisements

Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is a good way to learn more about programming languages  Interpreters are.
Assignments and Procs w/Params EOPL3 Chapter 4. Expressible vs. Denotable values Expressible Values –the language can express and compute these –represented.
Class 21: Imperative Programming University of Virginia cs1120 David Evans.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
CSE 341 Lecture 16 More Scheme: lists; helpers; let/let*; higher-order functions; lambdas slides created by Marty Stepp
CS 355 – PROGRAMMING LANGUAGES Dr. X. Apply-to-all A functional form that takes a single function as a parameter and yields a list of values obtained.
CSE341: Programming Languages Lecture 15 Mutation, Pairs, Thunks, Laziness, Streams, Memoization Dan Grossman Fall 2011.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Cs1120 Fall 2009 David Evans Lecture 20: Programming with State.
Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is aa good way to learn more about programming languages  Interpreters are.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
A Second Look At ML 1. Outline Patterns Local variable definitions A sorting example 2.
Recap form last time How to do for loops map, filter, reduce Next up: dictionaries.
Chapter SevenModern Programming Languages1 A Second Look At ML.
1 FP Foundations, Scheme In Text: Chapter Chapter 14: FP Foundations, Scheme Mathematical Functions Def: A mathematical function is a mapping of.
CSE 341 Lecture 8 curried functions Ullman 5.5 slides created by Marty Stepp
CSE 341 Lecture 21 delayed evaluation; thunks; streams slides created by Marty Stepp
CS314 – Section 5 Recitation 9
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Spring 2016.
CS314 – Section 5 Recitation 10
Additional Scheme examples
Functional Programming
Edited by Original material by Eric Grimson
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Winter 2013.
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Spring 2017.
6.001 SICP Variations on a Scheme
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Spring 2017.
CSE 341 Lecture 5 efficiency issues; tail recursion; print
CS 326 Programming Languages, Concepts and Implementation
Lists in Lisp and Scheme
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Autumn 2017.
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Winter 2013.
Env. Model Implementation
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Zach Tatlock Winter 2018.
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Spring 2013.
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Autumn 2018.
The Metacircular Evaluator
Lecture 28: Types of Types
FP Foundations, Scheme In Text: Chapter 14.
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Spring 2016.
slides created by Marty Stepp
Dynamic Scoping Lazy Evaluation
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Zach Tatlock Winter 2018.
CSE341: Programming Languages Section 9 Dynamic Dispatch Manually in Racket Zach Tatlock Winter 2018.
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Autumn 2017.
CS 36 – Chapter 11 Functional programming Features Practice
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Autumn 2018.
Winter 2018 With thanks to: Dan Grossman / Eric Mullen
6.001 SICP Further Variations on a Scheme
Streams, Delayed Evaluation and a Normal Order Interpreter
Lecture 13 - Assignment and the environments model Chapter 3
overview today’s ideas set-car! and set-cdr!
topics mutable data structures
6.001 SICP Variations on a Scheme
Mutators for compound data Stack Queue
Lecture 14: The environment model (cont
CSE 341 Lecture 27 JavaScript scope and closures
Dan Grossman / Eric Mullen Autumn 2017
Announcements Quiz 5 HW6 due October 23
6.001 SICP Interpretation Parts of an interpreter
CSE 341 Lecture 11 b closures; scoping rules
topics interpreters meta-linguistic abstraction eval and apply
CSE 341 Lecture 22 Macros; extending Scheme's syntax
CSE 341 Lecture 2 lists and tuples; more functions; mutable state
More Scheme CS 331.
Brett Wortzman Summer 2019 Slides originally created by Dan Grossman
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Spring 2019.
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Spring 2019.
Presentation transcript:

CSE 341 Lecture 20 Mutation; memoization slides created by Marty Stepp http://www.cs.washington.edu/341/

Mutation and mutability

Mutating variables (set! name expression) Unlike ML, in Scheme all top-level bindings are mutable! > (define x 3) ; int x = 3; > (set! x 5) ; x = 5; Legal, but changing bound values is generally discouraged. Convention: Any procedure that mutates ends with !

Mutations and environment What does the following code do to the environment? (define x 3) (define (f n) (+ n x)) (set! x 5) (define x 17) (define (g k) (* k x)) (set! x 8) symbol value system libraries... ... global environment symbol value x k (to be set on call) ... g's environment symbol value x n (to be set on call) ... f's environment

define vs. set! What is the difference between these two procedures? (define x 3) (define (f k) (define (g k) (define x 5) (set! x 5) (* x k)) (* x k)) both return the same thing for any given call, but... f defines a local x and uses it; global x is unchanged g mutates the global x and uses its new value

Mutation for "private" variables Use let to create a private mutable variable: (define incr null) ; stub for procedure (define get null) ; stub for procedure (let ((n 0)) (set! incr (lambda (i) ; replace stubs (set! n (+ n i)))) ; n += i (set! get (lambda () n))) ; return n > (get) > (incr 8) 0 > (get) > (incr 3) 11 > (get) > n 3 * reference to undefined ...

(We didn't care much about this distinction in ML... why?) Lists and equality (define L1 '(2 4 7)) (define L2 '(2 4 7)) (define L3 L2) Scheme lists are linked structures, as in ML two lists declared with the same value are separate lists one list declared to be another list will be a reference to that same list object in memory (shared) (We didn't care much about this distinction in ML... why?) 2 L1 4 7 2 L2 4 7 L3

Recall: Testing for equality (define L1 '(2 4 7)) (define L2 '(2 4 7)) (define L3 L2) (eq? expr1 expr2) ; reference/ptr comparison (eqv? expr1 expr2) ; compares values/numbers (= expr1 expr2) ; like eqv; numbers only (equal? expr1 expr2) ; deep equality test Which are true for L1 and L2? L3? 2 L1 4 7 2 L2 4 7 L3

Sharing between lists Which of the following are true? (define L4 (cons 8 L1)) (define L5 (append '(5 6) L2) Which of the following are true? (eq? L4 '(8 2 4 7)) (equal? L5 '(5 6 2 4 7)) (equal? L1 (cdr L4)) (eq? L1 (cdr L4)) (equal? L2 (cddr L5)) (eq? L2 (cddr L5)) (eq? L3 (cddr L5)) 2 L1 4 7 8 L4 2 L2 4 7 5 L5 6 L3

(set-car! and set-cdr! are disabled in "Pretty Big" Scheme) Mutating lists (set-car! list expr) (set-cdr! list expr) these procedures mutate the contents of lists (!) any reference to that list will see the change (set-car! L1 9) (set-cdr! L2 '(6 5 1)) (set-car! and set-cdr! are disabled in "Pretty Big" Scheme) 9 L1 4 7 L2 2 6 5 1 L3

(mutable lists are not allowed on our homework) (mcons expr mutableList) (mcar mutableList) (mcdr mutableList) (set-mcar! mutableList expr) (set-mcdr! mutableList expr) Scheme has a separate mutable list type that you can use to explicitly create a list that can be modified can build up a list by calling mcons with null mutable lists display on the interpreter with {...} (mutable lists are not allowed on our homework)

Memoization

Exercise Define a procedure count-factors that accepts an integer parameter and returns how many factors it has. Possible solution: (define (count-factors n) (length (filter (lambda (x) (= 0 (modulo n x))) (range 1 n)))) Problem: slow for large values; "forgets" after each call > (count-factors 999990) 48 ; takes 4-5 seconds 48 ; takes 4-5 seconds, AGAIN!

Memoization memoization: Optimization technique of avoiding re-calculating results for previously-processed function calls. often uses a cache of previously computed values General algorithmic pattern: function compute(param): if I have never computed the result for this value of param before: compute the result for param. store (param, result) into cache data structure. return result. else // I have computed this result before; don't re-compute look up (param, result) in cache data structure. memoization is related to the idea of dynamic programming, which means breaking down a problem into smaller, often overlapping, sub-problems

Memoization w/ association lists a natural structure to cache prior calls is a map recall: Scheme implements maps as association lists > (define phonebook (list '(Marty 6852181) '(Stuart 6859138) '(Jenny 8675309))) > (assoc 'Stuart phonebook) (Stuart 6859138) > (cdr (assoc 'Jenny phonebook)) ; get value 8675309 we'll remember results of past calls to count-factors by storing them in a (mutating) association list

Memoizing count-factors code ; cache of past calls as (n . count) pairs; initially empty (define cache null) (define (count-factors n) (define (divides? x) (= 0 (modulo n x))) ; look up n in the cache (see if we computed it before) (let ((memory (assoc n cache))) (if memory ; if n is in cache, return cached value. (cdr memory) ; else, count the factors... (let ((count (length (filter divides? (range 1 n))))) ; store them into the cache... (set! cache (cons (cons n count) cache)) ; and return the result. count))))

Problem: undesired global cache the cache is a global variable can be seen (or modified!) by other code solution: define it locally to do this properly, we must define count-factors using an inner helper and local inner cache count-factors is set equal to its own helper bizarre, but ensures proper closure over the local cache

Improved count-factors code (define count-factors (let ((cache null)) ; local cache; initially empty ; inner helper that has access to the local cache (define (helper n) (define (divides? x) (= 0 (modulo n x))) ; look up n in the cache (see if we computed it before) (let ((memory (assoc n cache))) (if memory ; if n is in cache, return cached value. (cdr memory) ; else, count the factors... (let ((count (length (filter divides? (range 1 n))))) ; store them into the cache... (set! cache (cons (cons n count) cache)) ; and return the result. count)))) helper)) ; return helper; sets count-factors equal to helper