Practice session #6: 1. Sequence operations 2. Partial evaluation with currying 3. Lazy-lists.

Slides:



Advertisements
Similar presentations
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 5. 2 List Utilities Scheme built-in procedures –(list x y z...) –(list-ref lst index) –(length lst) –(append.
Advertisements

Programming with Lists
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.
1 Programming Languages and Paradigms Lisp Programming.
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
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
מבוא מורחב - שיעור 91 Lecture 9 Lists continued: Map, Filter, Accumulate, Lists as interfaces.
Cs7100(Prasad)L11Clos1 Closures and Streams. Contemporary Interest in Closures The concept of closures was developed in the 1960s and was first fully.
מבוא מורחב - שיעור 15 1 Lecture 15 Streams. מבוא מורחב - שיעור 15 2 Streams: Motivation (define (sum-primes a b) (define (iter count accum) (cond ((>
6.001 SICP SICP – October HOPs, Lists, Trees Trevor Darrell 32-D512 Office Hour: W web page:
Chapter 15 Functional Programming Languages. Copyright © 2007 Addison-Wesley. All rights reserved. 1–2 Introduction Design of imperative languages is.
מבוא מורחב - שיעור 81 Lecture 8 Lists and list operations (continue).
( (lambda (z) (define x (lambda (x) (lambda (y z) (y x)))) ( ( (x (lambda () z)) (lambda (z) z) 3 ) ) ) 2)
מבוא מורחב 1 Lecture #8. מבוא מורחב 2 Shall we have some real fun.. Lets write a procedure scramble.. (scramble (list )) ==> ( ) (scramble.
PPL Pairs, lists and data abstraction. Data Abstraction? An interface: separate implementation from usage Think of the Map interface in Java: we know.
PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.
Spring 2008Programming Development Techniques 1 Topic 6 Hierarchical Data and the Closure Property Section September 2008.
Closures and Streams More on Evaluations CS784(pm)1.
1 Lecture OO, the notion of inheritance 3 Stacks in OO style (define (make-stack) (let ((top-ptr '())) (define (empty?) (null? top-ptr)) (define.
CSC3315 (Spring 2009)1 CSC 3315 Programming Paradigms Scheme Language Hamid Harroud School of Science and Engineering, Akhawayn University
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
1 Append: process  (append list1 list2) (cons 1 (append ‘(2) list2)) (cons 1 (cons 2 (append ‘() list2))) (cons 1 (cons 2 list2)) (define (append list1.
Today’s topic: Abstraction Compound Data Data Abstractions: Isolate use of data abstraction from details of implementation Relationship between data abstraction.
Practice session 6 Sequence Operations Partial Evaluation Lazy Lists.
PPL Lazy Lists. Midterm 2012 (define sum-vals (λ (ts) (if (ts-simple? ts) (ts-val ts) (accumulate + 0 (map ts-val (ts-inner-slots ts))))))
Fall 2008Programming Development Techniques 1 Topic 8 Sequences as Conventional Interfaces Section October 2008.
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 8. Outline 1.The special form quote 2.Data abstraction: Trie 3.Alternative list: Triplets 4.Accumulate-n.
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 6. 2 List Utilities Scheme built-in procedures –(list x y z...) –(list-ref lst index) –(length lst) –(append.
Functional Programming. Some Functional Languages Lisp Scheme - a dialect of Lisp Haskell Miranda.
Principles Of Programming Languages Lecture 2 Today Design-By-Contract Data Structures: Lists and Pairs Iteration vs. Recursion If we have time: live.
Additional Scheme examples
CS 550 Programming Languages Jeremy Johnson
ML: a quasi-functional language with strong typing
Lecture 16 Streams continue Infinite Streams מבוא מורחב - שיעור 16.
Pairs and Lists. Data Abstraction. SICP: Sections – 2.2.1
PPL Lecture Notes: Chapter 3 High-Order Procedures Revisited.
PPL Lazy Lists.
(defmacro (delay x) (list 'lambda () x))
Racket CSC270 Pepper major portions credited to
September 4, 1997 Programming Languages (CS 550) Lecture 6 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts.
Closures and Streams cs784(Prasad) L11Clos
CS 270 Math Foundations of CS Jeremy Johnson
COP4020 Programming Languages
Env. Model Implementation
Binomial Priority Queues
6.001 SICP Data abstractions
Streams Sections 3.5.1,3.5.2 Pages
Lecture 18 Infinite Streams and
PPL Sequence Interface.
Lecture 18.
Lecture #8 מבוא מורחב.
6.001 SICP Streams – the lazy way
Chapter 4 Data and Behavior Abstraction
Streams, Delayed Evaluation and a Normal Order Interpreter
6.001 SICP Data abstractions
Announcements Quiz 5 HW6 due October 23
Lecture #7 מבוא מורחב.
List and list operations (continue).
Lecture # , , , , מבוא מורחב.
Lecture 13: Assignment and the Environment Model (EM)
Binomial Priority Queues
CS 403: Programming Languages
More Scheme CS 331.
Streams Contract is the same as pairs...
Presentation transcript:

Practice session #6: 1. Sequence operations 2. Partial evaluation with currying 3. Lazy-lists

2 Motivation: The procedure signs maps a collection of numbers to their sign. 1. The sequence operations For (int i=0; i<arrayLength; i++) { if (a[i] == 0) b[i] = 0 ; else b[i] = a[i]/abs(a[i]); } For (int i=0; i<arrayLength; i++) { if (a[i] == 0) b[i] = 0 ; else b[i] = a[i]/abs(a[i]); } In C: Signature: signs(ls) Example: (signs(list ))=> '( ) Type: [List(Number)->List(Number)] (define signs (lambda (ls) (if (null? ls) ls (if (= 0 (car ls)) (cons 0 (signs (cdr ls)))) (cons (/ (car ls) (abs (car ls))) (signs (cdr ls))))))) Signature: signs(ls) Example: (signs(list ))=> '( ) Type: [List(Number)->List(Number)] (define signs (lambda (ls) (if (null? ls) ls (if (= 0 (car ls)) (cons 0 (signs (cdr ls)))) (cons (/ (car ls) (abs (car ls))) (signs (cdr ls))))))) In Scheme:

3 Motivation: The procedure signs maps a collection of numbers to their sign. 1. The sequence operations Signature: map(proc,items) Purpose: Apply 'proc' to all 'items'. Type: [[T1 -> T2]*List(T1) -> List(T2)] Signature: map(proc,items) Purpose: Apply 'proc' to all 'items'. Type: [[T1 -> T2]*List(T1) -> List(T2)] The sequence operation map: Signature: signs-map(ls) Example: (signs(list ))=> '( ) Type: [List(Number)->List(Number)] (define signs-map (lambda (ls) (map (lambda (x) (if (= x 0) 0 (/ x abs(x)))) ls))) Signature: signs-map(ls) Example: (signs(list ))=> '( ) Type: [List(Number)->List(Number)] (define signs-map (lambda (ls) (map (lambda (x) (if (= x 0) 0 (/ x abs(x)))) ls))) Implementation using sequence operations:

4 1. The sequence operations The procedure partition divides a list into two lists according to some predicate. For example: > (partition number? (list 1 2 ‘a 4 ‘b #t)) ‘((1 2 4) ‘a ‘b #t) Implement the procedure partition, using the sequence operation filter. The sequence operation filter: Signature: filter(predicate, sequence) Purpose: return a list of all elements satisfying the predicate. Type:[[T-> Boolean]*List(T) -> List(T)] Post-condition: x in result x in sequence, and (eq? #t (predicate x)) Signature: filter(predicate, sequence) Purpose: return a list of all elements satisfying the predicate. Type:[[T-> Boolean]*List(T) -> List(T)] Post-condition: x in result x in sequence, and (eq? #t (predicate x)) Additional sequence operations:

5 1. The sequence operations The procedure partition, using the sequence operation filter: Signature: partition(predicate, sequence) Type: [[T-> Boolean]*List(T) -> Pair(List(T),List(T))] Example: (partition number? (list 1 (cons 1 2) 3 4 (cons 0))) => '((1 3 4) (1. 2) (0. 3)) (partition number? (list 1 2 'a 'b 3 4 'd #t)) => '(( ) a b d #t) (define partition (lambda (pred seq) (cons (filter pred seq) (filter (lambda (x) (not (pred x))) seq)))) Signature: partition(predicate, sequence) Type: [[T-> Boolean]*List(T) -> Pair(List(T),List(T))] Example: (partition number? (list 1 (cons 1 2) 3 4 (cons 0))) => '((1 3 4) (1. 2) (0. 3)) (partition number? (list 1 2 'a 'b 3 4 'd #t)) => '(( ) a b d #t) (define partition (lambda (pred seq) (cons (filter pred seq) (filter (lambda (x) (not (pred x))) seq)))) Additional sequence operations:

6 1. The sequence operations For example: > (accumulate + 0 (list )) 15 > (accumulate expt 1 (list 4 3 2)) The sequence operation accumulate: Signature: accumulate(op,initial,sequence) Purpose: Accumulate by 'op' all sequence elements, starting (ending) with 'initial' Type: [[T1*T2 -> T2]*T2*List(T1) -> T2] Post-condition: result=(initial op (seq[n] (op...(op seq[1])))) Signature: accumulate(op,initial,sequence) Purpose: Accumulate by 'op' all sequence elements, starting (ending) with 'initial' Type: [[T1*T2 -> T2]*T2*List(T1) -> T2] Post-condition: result=(initial op (seq[n] (op...(op seq[1])))) 4^(3^(2^1)) = ≠ 4096 = ((4^3)^2)^1 Additional sequence operations:

7 1. The sequence operations > (define ls (list (list 1 2 3) (list 4 6 7) (list 8 9))) > (flatmap cdr ls) '( ) > (flatmap (lambda (x) (map sqr x)) ls) '( ) > (flatmap (lambda (lst) (filter odd? lst)) ls) '( ) Signature: flatmap(proc, seq) Type:[[T1->List(T2)] * List(T1) -> List(T2)] Purpose: 1. Applies a function on every element of the given list, resulting in a new nested list. 2. Flattens the nested list (not recursively). Signature: flatmap(proc, seq) Type:[[T1->List(T2)] * List(T1) -> List(T2)] Purpose: 1. Applies a function on every element of the given list, resulting in a new nested list. 2. Flattens the nested list (not recursively). Question 1: flatmap (define flatmap (lambda (proc seq) (accumulate append (list) (map proc seq)))) (define flatmap (lambda (proc seq) (accumulate append (list) (map proc seq))))

8 1. The sequence operations Signature: flat-sum(ls) Type: [List -> Number] Precondition: ls is recursively made of lists and numbers only. Examples: (flat-sum '(1 2 3 (1 2 (1 ( ) 2 3 ( ) 4) 3 4) 4)) => 50 (flat-sum '( )) => 10 Signature: flat-sum(ls) Type: [List -> Number] Precondition: ls is recursively made of lists and numbers only. Examples: (flat-sum '(1 2 3 (1 2 (1 ( ) 2 3 ( ) 4) 3 4) 4)) => 50 (flat-sum '( )) => 10 Question 2: flat-sum (define flat-sum (lambda (ls) (cond ((null? ls) 0) ((number? ls) ls) ((let ((car-sum (flat-sum (car ls))) (cdr-sum (flat-sum (cdr ls)))) (+ car-sum cdr-sum)))))) (define flat-sum (lambda (ls) (cond ((null? ls) 0) ((number? ls) ls) ((let ((car-sum (flat-sum (car ls))) (cdr-sum (flat-sum (cdr ls)))) (+ car-sum cdr-sum)))))) Implementation without sequence operations:

9 1. The sequence operations Signature: flat-sum(ls) Type: [List -> Number] Precondition: ls is recursively made of lists and numbers only. Examples: (flat-sum '(1 2 3 (1 2 (1 ( ) 2 3 ( ) 4) 3 4) 4)) => 50 (flat-sum '( )) => 10 Signature: flat-sum(ls) Type: [List -> Number] Precondition: ls is recursively made of lists and numbers only. Examples: (flat-sum '(1 2 3 (1 2 (1 ( ) 2 3 ( ) 4) 3 4) 4)) => 50 (flat-sum '( )) => 10 Question 2: flat-sum (define flat-sum (lambda (lst) (acc + 0 (map (lambda (x) (if (number? x) x (flat-sum x))) ls)))) (define flat-sum (lambda (lst) (acc + 0 (map (lambda (x) (if (number? x) x (flat-sum x))) ls)))) Implementation with sequence operations: Q: Could you think of a way to improve this Implementation?

10 1. The sequence operations Signature: flat-sum(ls) Type: [List -> Number] Precondition: ls is recursively made of lists and numbers only. Examples: (flat-sum '(1 2 3 (1 2 (1 ( ) 2 3 ( ) 4) 3 4) 4)) => 50 (flat-sum '( )) => 10 Signature: flat-sum(ls) Type: [List -> Number] Precondition: ls is recursively made of lists and numbers only. Examples: (flat-sum '(1 2 3 (1 2 (1 ( ) 2 3 ( ) 4) 3 4) 4)) => 50 (flat-sum '( )) => 10 Question 2: flat-sum (define flat-sum (let ((node->number (lambda (x) (if (number? x) x (flat-sum x))))) (lambda (lst) (acc + 0 (map node->number ls))))) (define flat-sum (let ((node->number (lambda (x) (if (number? x) x (flat-sum x))))) (lambda (lst) (acc + 0 (map node->number ls))))) Implementation with sequence operations: Q: How many closures are generated now?

11 1. The sequence operations Signature: maximum(lst) Type: [List(Number)->Number] Pre-Condition: lst contains only natural numbers (define maximum (lambda (lst) (acc (lambda (a b) (if (> a b) a b)) 0 lst))) Signature: maximum(lst) Type: [List(Number)->Number] Pre-Condition: lst contains only natural numbers (define maximum (lambda (lst) (acc (lambda (a b) (if (> a b) a b)) 0 lst))) Question 3: Sorting a list Signature: insertion-sort(lst) Type: [List(Number)->List(Number)] (define insertion-sort (lambda (lst) (if (null? lst) lst (let* ((max (maximum lst)) (rest (filter (lambda (x) (not (= max x))) lst))) (cons max (insertion-sort rest)))))) Signature: insertion-sort(lst) Type: [List(Number)->List(Number)] (define insertion-sort (lambda (lst) (if (null? lst) lst (let* ((max (maximum lst)) (rest (filter (lambda (x) (not (= max x))) lst))) (cons max (insertion-sort rest)))))) Implementation with sequence operations:

12 2. Partial evaluation with Currying Signature: accumulate(op,initial,sequence) Purpose: Accumulate by ’op’ all sequence elements, starting (ending) with ’initial’ Type: [[T1*T2 -> T2]*T2*LIST(T1) -> T2] (define accumulate (lambda (op initial sequence) (if (null? sequence) initial (op (car sequence) (accumulate op initial (cdr sequence)))))) Signature: accumulate(op,initial,sequence) Purpose: Accumulate by ’op’ all sequence elements, starting (ending) with ’initial’ Type: [[T1*T2 -> T2]*T2*LIST(T1) -> T2] (define accumulate (lambda (op initial sequence) (if (null? sequence) initial (op (car sequence) (accumulate op initial (cdr sequence)))))) Question 4: Currying a recursive function - accumulate Recall the implementation of accumulate: Q: How would you Curry the procedure accumulate, delaying the sequence parameter?

13 2. Partial evaluation with Currying Signature: c-accumulate-naive (op,initial) Type: [[[T*T->T]*T ->[List(T)->T]] Purpose: Partial application of accumulate (by operator and initial) (define c-accumulate-naive (lambda (op initial) (lambda (sequence) (if (null? sequence) initial (op (car sequence) ((c-accumulate-naive op initial) (cdr sequence))))))) Signature: c-accumulate-naive (op,initial) Type: [[[T*T->T]*T ->[List(T)->T]] Purpose: Partial application of accumulate (by operator and initial) (define c-accumulate-naive (lambda (op initial) (lambda (sequence) (if (null? sequence) initial (op (car sequence) ((c-accumulate-naive op initial) (cdr sequence))))))) Question 4: Currying a recursive function - accumulate Naïve Currying of accumulate:

14 2. Partial evaluation with Currying Signature: c-accumulate-op-initial (op,initial) Type:[[[T*T->T]*T ->[List(T)->T]] Purpose: Partial application of accumulate (by operator and initial) (define c-accumulate-op-initial (lambda (op initial) (letrec ((iter (lambda (sequence) (if (null? sequence) initial (op (car sequence) (iter (cdr sequence))))))) iter))) Signature: c-accumulate-op-initial (op,initial) Type:[[[T*T->T]*T ->[List(T)->T]] Purpose: Partial application of accumulate (by operator and initial) (define c-accumulate-op-initial (lambda (op initial) (letrec ((iter (lambda (sequence) (if (null? sequence) initial (op (car sequence) (iter (cdr sequence))))))) iter))) Question 4: Currying a recursive function - accumulate A better version: >(define add-accum (c-accumulate-op-initial + 0)) >(add-accum '(1 2 3)) 6 >(add-accum '(4 5 6)) 15

2. Partial evaluation with Currying Signature: c-accumulate-sequence(seq) Type: [List(T)-> [[T*T->T]*T->T ] Purpose: Curried version of accumulate (by sequence) (define c-accumulate-sequence (lambda (sequence) (if (null? sequence) (lambda (op initial) initial) (let ((rest (c-accumulate-sequence (cdr sequence)))) (lambda (op initial) (op (car sequence) (rest op initial))))))) Signature: c-accumulate-sequence(seq) Type: [List(T)-> [[T*T->T]*T->T ] Purpose: Curried version of accumulate (by sequence) (define c-accumulate-sequence (lambda (sequence) (if (null? sequence) (lambda (op initial) initial) (let ((rest (c-accumulate-sequence (cdr sequence)))) (lambda (op initial) (op (car sequence) (rest op initial))))))) Question 4: Currying a recursive function - accumulate Currying by the sequence parameter: >(define lst-accum (c-accumulate-sequence '(1 2 3))) >(lst-accum + 0) 6 >(lst-accum * 1) 6

16 2. Partial evaluation with Currying Signature: dists_k(ls,k) Type: [List(Number*Number) -> List(Number)] Examples: (dists_k (list (cons 3 4) (cons 3 7) (cons 15 12) (cons 3 12)) 3) => '( ) Signature: dists_k(ls,k) Type: [List(Number*Number) -> List(Number)] Examples: (dists_k (list (cons 3 4) (cons 3 7) (cons 15 12) (cons 3 12)) 3) => '( ) Question 5: Using filter an map Implement the procedure dists_k: (define dists_k (lambda (ls k) (if (null? ls) ls (let ((xcord (caar ls)) (ycord (cdar ls)) (rest (dists_k (cdr ls) k))) (if (= xcord k) (cons (dist xcord ycord) rest) rest))))) (define dists_k (lambda (ls k) (if (null? ls) ls (let ((xcord (caar ls)) (ycord (cdar ls)) (rest (dists_k (cdr ls) k))) (if (= xcord k) (cons (dist xcord ycord) rest) rest))))) Implementation without sequence operations:

17 2. Partial evaluation with Currying Signature: dists_k(ls,k) Type: [List(Number*Number) -> List(Number)] Examples: (dists_k (list (cons 3 4) (cons 3 7) (cons 15 12) (cons 3 12)) 3) => '( ) Signature: dists_k(ls,k) Type: [List(Number*Number) -> List(Number)] Examples: (dists_k (list (cons 3 4) (cons 3 7) (cons 15 12) (cons 3 12)) 3) => '( ) Question 5: Using filter an map Implement the procedure dists_k: (define dists_k (lambda (ls k) (map (lambda (x) (dist (car x) (cdr x))) (filter (lambda (x) (= (car x) k)) ls)))) (define dists_k (lambda (ls k) (map (lambda (x) (dist (car x) (cdr x))) (filter (lambda (x) (= (car x) k)) ls)))) Implementation with sequence operations: Q: Could you think of a way to improve this Implementation? A list of pairs with X-coordinate equal to k.

18 2. Partial evaluation with Currying Question 5: Using filter an map (define dist (lambda (x y) (sqrt (+ (sqr x) (sqr y))))) Examine the procedure dist: (define dists_k (lambda (ls k) (map (lambda (x) (dist (car x) (cdr x))) (filter (lambda (x) (= (car x) k)) ls)))) (define dists_k (lambda (ls k) (map (lambda (x) (dist (car x) (cdr x))) (filter (lambda (x) (= (car x) k)) ls)))) A list of pairs with X-coordinate equal to k.

19 2. Partial evaluation with Currying Question 5: Using filter an map (define dist (lambda (x y) (sqrt (+ (sqr x) (sqr y))))) Examine the procedure dist: (define dists_k (lambda (ls k) (map (lambda (x) (dist (car x) (cdr x))) (filter (lambda (x) (= (car x) k)) ls)))) (define dists_k (lambda (ls k) (map (lambda (x) (dist (car x) (cdr x))) (filter (lambda (x) (= (car x) k)) ls)))) A list of pairs with X-coordinate equal to k. (define c_dist (lambda (x) (let ((xx (sqr x))) (lambda (y) (sqrt (+ (sqr y) xx)))))) (define c_dist (lambda (x) (let ((xx (sqr x))) (lambda (y) (sqrt (+ (sqr y) xx)))))) A curried version of the procedure dist:

20 2. Partial evaluation with Currying Question 5: Using filter an map (define dists_k (lambda (ls k) (map (lambda (x) (dist (car x) (cdr x))) (filter (lambda (x) (= (car x) k)) ls)))) (define dists_k (lambda (ls k) (map (lambda (x) (dist (car x) (cdr x))) (filter (lambda (x) (= (car x) k)) ls)))) A list of pairs with X-coordinate equal to k. (define dists_k (lambda (ls k) (let ((dist_k (c_dist k))) (map (lambda (x) (dist_k (cdr x))) (filter (lambda (x) (= (car x) k)) ls))))) (define dists_k (lambda (ls k) (let ((dist_k (c_dist k))) (map (lambda (x) (dist_k (cdr x))) (filter (lambda (x) (= (car x) k)) ls))))) New version of dists_k:

21 3. Lazy lists Some reminders: 1.Lazy-lsits are serial data-structures that allow delayed computation. 2.There is no need to store the entire list elements in memory. 3.Lazy-lists may represent infinite series. 4.The type of Lazy-lists is defined recursively: LazyList = {()} union T*[Empty->LazyList] Signature: cons(head, tail) Type: [T * [Empty->LazyList] -> LazyList] Purpose: Value constructor for lazy lists Signature: cons(head, tail) Type: [T * [Empty->LazyList] -> LazyList] Purpose: Value constructor for lazy lists Signature: head(lzl) Type:[LazyList -> T] Purpose: Selector for the first item of lzl (a lazy list) Pre-condition: lzl is not empty Signature: head(lzl) Type:[LazyList -> T] Purpose: Selector for the first item of lzl (a lazy list) Pre-condition: lzl is not empty Signature: tail(lzl) Type: [LazyList -> LazyList] Purpose: Selector for the tail (all but the first item) of lzl (a lazy list) Pre-condition: lzl is not empty Signature: tail(lzl) Type: [LazyList -> LazyList] Purpose: Selector for the tail (all but the first item) of lzl (a lazy list) Pre-condition: lzl is not empty

22 3. Lazy lists Some reminders: 1.Lazy-lsits are serial data-structures that allow delayed computation. 2.There is no need to store the entire list elements in memory. 3.Lazy-lists may represent infinite series. 4.The type of Lazy-lists is defined recursively: LazyList = {()} union T*[Empty->LazyList] Signature: take(lzl,n) Type: [LazyList * Number-> List] Purpose: Creates a List out of the first n items of lzl (a lazy list) Pre-condition: lzl length is at least n, n is a natural number Post-condition: result[i]=lzl[i] for any i in range 0::n-1 Signature: take(lzl,n) Type: [LazyList * Number-> List] Purpose: Creates a List out of the first n items of lzl (a lazy list) Pre-condition: lzl length is at least n, n is a natural number Post-condition: result[i]=lzl[i] for any i in range 0::n-1 Signature: nth(lzl,n) Type: [LazyList * Number-> T] Purpose: Gets the n-th item of lzl (a lazy list) Pre-condition: lzl length is at least n, n is a natural number Post-condition: result=lzl[n-1] Signature: nth(lzl,n) Type: [LazyList * Number-> T] Purpose: Gets the n-th item of lzl (a lazy list) Pre-condition: lzl length is at least n, n is a natural number Post-condition: result=lzl[n-1]

23 3. Lazy lists Examples: Signature: integers-from(low) Purpose: Create a lazy-list containing all integers bigger than n-1 by their order. Pre-condition: n is an integer (define integers-from (lambda (n) (cons n (lambda () (integers-from (+ 1 n)))))) Signature: integers-from(low) Purpose: Create a lazy-list containing all integers bigger than n-1 by their order. Pre-condition: n is an integer (define integers-from (lambda (n) (cons n (lambda () (integers-from (+ 1 n)))))) >(head (integers-from 5)) 5 >(head (tail (integers-from 5))) 6

24 3. Lazy lists (define seven-boom! (lambda (n) (cons (cond ((= (modulo n 7) 0) 'boom) ((has-digit? n 7) 'boom) ((= (modulo (sum-digits? n) 7) 0) 'boom) (else n)) (lambda () (seven-boom! (+ n 1)))))) (define seven-boom! (lambda (n) (cons (cond ((= (modulo n 7) 0) 'boom) ((has-digit? n 7) 'boom) ((= (modulo (sum-digits? n) 7) 0) 'boom) (else n)) (lambda () (seven-boom! (+ n 1)))))) Question 6: 7-Boom >(seven-boom! 1) ‘(1. # ) >(take (seven-boom! 1) 7) ‘( boom)

25 3. Lazy lists Question 7: Collatz conjecture For every n>1, the sequence of numbers (n,f(f),f(f(n)),…) eventually reaches 1. For example: 563 -> > 845 -> … 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1 (define lzl-collatz (lambda (n) (if (< n 2) (cons n (lambda () (list))) (cons n (lambda () (if (= (modulo n 2) 0) (lzl-collatz (/ n 2)) (lzl-collatz (+ (* 3 n) 1 )))))))) (define lzl-collatz (lambda (n) (if (< n 2) (cons n (lambda () (list))) (cons n (lambda () (if (= (modulo n 2) 0) (lzl-collatz (/ n 2)) (lzl-collatz (+ (* 3 n) 1 )))))))) > (take (lzl-collatz 563) 44) '( )

26 3. Lazy lists Question 8: lzl-filter Signature: lzl-filter(pred lzl) Type: [[T -> Bool] * LazyList-> LazyList] Purpose: Creates a lazy list containing all members of lzl that fit the criteria pred (define lzl-filter (lambda (pred lzl) (cond ((null? lzl) lzl) ((pred (head lzl)) (cons (head lzl) (lambda () (lzl-filter pred (tail lzl))))) (else (lzl-filter pred (tail lzl)))))) Signature: lzl-filter(pred lzl) Type: [[T -> Bool] * LazyList-> LazyList] Purpose: Creates a lazy list containing all members of lzl that fit the criteria pred (define lzl-filter (lambda (pred lzl) (cond ((null? lzl) lzl) ((pred (head lzl)) (cons (head lzl) (lambda () (lzl-filter pred (tail lzl))))) (else (lzl-filter pred (tail lzl)))))) > (lzl-filter (lambda (n) (= (modulo n 3) 0)) (integers-from 0)) Q: How could we generate the lazy-list of all integers that are divisible by 3?

27 3. Lazy lists Question 8: Lazy list of prime numbers (define primes (cons 2 (lambda () (lzl-filter prime? (integers-from 3))))) (define primes (cons 2 (lambda () (lzl-filter prime? (integers-from 3))))) > (take primes 6) ’( ) (define prime? (lambda (n) (letrec ((iter (lambda (lz) (cond ((> (sqr (head lz)) n) #t) ((divisible? n (head lz)) #f) (else (iter (tail lz))))) )) (iter primes)) )) (define prime? (lambda (n) (letrec ((iter (lambda (lz) (cond ((> (sqr (head lz)) n) #t) ((divisible? n (head lz)) #f) (else (iter (tail lz))))) )) (iter primes)) ))

28 3. Lazy lists Question 8: Lazy list of prime numbers (define sieve (lambda (lz) (cons (head lz) (lambda () (sieve (lzl-filter (lambda (x) (not (divisible? x (head lz)))) (tail lz))))) )) (define primes1 (sieve (integers-from 2))) (define sieve (lambda (lz) (cons (head lz) (lambda () (sieve (lzl-filter (lambda (x) (not (divisible? x (head lz)))) (tail lz))))) )) (define primes1 (sieve (integers-from 2))) > (take primes1 7) ’( )