Chapter 4, Metalinguistic Abstraction
Exercise 4.32
I implemented a simple example which shows the difference between streams and lazier lazy lists, the example just demostrates that even ‘car’ is not evaluated unless it is accessed.
Streams:
1
2
3
4
5
6
7
1 ]=> (define test (lambda() (display 'invoked) 1))
;Value: test
1 ]=> (cons-stream (test) (test))
invoked
;Value 76: (1 . #[compound-procedure 77])
Lazier lazy:
1
2
3
4
5
6
7
8
9
10
11
;;; L-Eval input:
(define test (lambda() (display 'invoked) 1))
;;; L-Eval value:
ok
;;; L-Eval input:
(cons (test) (test))
;;; L-Eval value:
(compound-procedure (m) ((m x y)) <procedure-env>)
Take advantage of extra laziness
First, I thought of infinite lists in both directions but soon realised that this can be done with streams too. Similarly we can implement infinite trees too using streams(hint: cons of cons).
So, the only case where I found that extra laziness is giving extra advantage is circular dependencies which in the text is already demonstrated for solving first order differential equations.