SICP-Notes-Lecture 20 Streams

Lecture 20 Streams

These are my notes for SICP(Structure and Interpretation of Computer Programs). Hope they’ll be of some help to you.

Lazy Evaluation in Scheme

Streams are similar to lists, except that the tail of a stream is not evaluated until we ask to do it. This allows streams to be used to represent infinitely long lists.

Lazy evaluation
  • In Python, iterators and generators allow for lazy evaluation
def ints(first):
    while True:
        yield first
        first += 1
>>> s = ints(1)
>>> next(s)
1
>>> next(s)
2
  • Scheme doesn’t have iterators. How about a list?
(define (ins first)
  (cons first (ints (+ first 1))))
scm> (ints 1)
maximum recursion depth exceeded

Second argument to cons is always evaluated.

Streams

Instead of iterators, Scheme uses streams.

(define (ints first)
  (cons-stream first
               (ints (+ first 1))))
scm> (ints 1)
(1 . #[promise (not forced)]) ;Lazy evaluation, just like iterators in Python
  • Stream: (linked) list whose rest is lazily evaluated
    • A promise to compute
  • cdr returns the rest of a list
    • For normal lists, the rest is another list
    • The rest of a stream is a promise to compute the list.
  • cdr-stream forces Scheme to compute the rest
scm> (define s (cons-stream 1 (cons-stream 2 nil))) ;Remember, a stream is just a regular Scheme pair whose second element is a promise
s
scm> s
(1 . #[promise (not forced)])
scm> (car s)
1
scm> (cdr s)
#[promise (not forced)]
scm> (cdr-stream s)
(2 . #[promise (not forced)])
scm> (cdr-stream (cdr-stream s))
()
Promises: delay
  • Promise: an object that delays evaluation of an expression

    • The delay special form creates promises
    scm> (print 5) ;(print 5) is immediately evaluated
    5
    scm> (delay (print 5)) ;(print 5) is not evaluated yet
    #[promise (not forced)]
    
Promises: force
  • The delay special form creates promises
  • The force procedure evaluates the expression inside the promise
scm> (define x (delay (print 5))) ;(print 5) is not evaluated yet
x
scm> x
#[promise (not forced)]
scm> (force x) ;Evaluates (print 5)
5
;Error in our interpreter
scm> x
#[promise (forced)]

cons-stream and cdr-stream are syntactic sugar. Achieve the same effect with delay and force

scm> (define s (cons-stream 1 nil))
s
scm> s
(1 . #[promise (not forced)])
scm> (cdr-stream s)
()
scm> (define s (cons 1 (delay nil)))
s
scm> s
(1 . #[promise (not forced)])
scm> (force (cdr s))
()
Recursively defined streams - Constant stream

Let’s start with the constant stream. A constant stream is an infinitely long stream with a number repreated.

(define (constant-stream i)
  (cons-stream i (constant-stream i)))
scm> (define ones (constant-stream 1))
scm> (car ones)
1
scm> (car (cdr-stream ones))
1

Let’s define the naturals stream which is an infinitely long stream with the natural numbers starting at start.

(define (nats start)
  (cons-stream start (nats (+ start 1))))
scm> (define s (nats 0))
scm> (car s)
0
scm> (car (cdr-stream s))
1
scm> (car (cdr-stream (cdr-stream s)))
2

Let’s write a function that will add two infinite streams together and return a new stream.

(define (add-stream s1 s2)
  (cons-stream (+ (car s1) (car s1))
               (add-stream (cdr-stream s1) (cdr-stream s2))))

Let’s use the ones stream we’ve defined before and our new add-stream function to define the ints stream. This is the same as (nats 1). How do we do this?

(define ints (cons-stream 1 (add-stream ints ones)))
;We can use infinite streams to build other infinite streams. This is the power of lazy evalluation, our current stream stays one step ahead of itself!
Examples: map-stream
  • Implement (map-stream fn s):
    • fn is a one-argument function
    • s is a stream
  • Returns a new stream with fn applied to elements of s
(define (map-stream fn s)
  (if (null? s) nil
  (cons-stream (fn (car s)) (map-stream fn (cdr-stream s)))))
Examples: stream-to-list
  • Implement (stream-to-list s num-elements):
    • s is a stream
    • num-elements is a non-negative integer
  • Returns a Scheme list containing the first num-elements elements of s
scm> (stream-to-list (ints 1) 10)
(1 2 3 4 5 6 7 8 9 10)
(define (stream-to-list s num-elements)
  (if (or (= num-elements 0) (null? s)) nil
      (cons (car s)
            (stream-to-list (cdr-stream s) (- num-elements 1)))))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值