A ** stream** is a potentially infinite lazy list. It evaluates
its

`cdr`

and maybe also its `car`

only when demanded. It supports
the same operations as lists, with one additional operation:
- $nil
- $null?
- $cons
- $car
- $cdr
- $append
- make-stream

`make-stream`

takes
a thunk and returns a stream. We can implement these functions using
memoization as follows.
(define $cons cons) (define $null? null?) (define $nil '()) (define $car (lambda (s) (if (pair? s) (car s) (car (s))))) (define $cdr (lambda (s) (if (pair? s) (cdr s) (cdr (s))))) (define $append (lambda (a b) (make-stream (lambda () (if ($null? a) b ($cons ($car a) ($append ($cdr a) b))))))) (define memo (lambda (p) (let ((first #t) (val #f)) (lambda () (if first (begin (set! first $f) (set! val (p))) val))))) (define make-stream memo)Recall the question the on the mid-term that asked you to write

`same-fringe?`

. We can do that by transforming a tree into
a stream and calling `$equal`

.
(define tree->stream (lambda (t) (make-stream (lambda () (if (symbol? t) ($cons t $nil) ($append (tree->stream (car t)) (tree->stream (cdr t)))))))) (define $equal (lambda (s1 s2) (cond ((and ($null? s1) ($null? s2)) #t) ((or ($null? s1) ($null? s2)) #f) (else (and (eq? ($car s1) ($car s2)) ($equal ($cdr s1) ($cdr s2))))))) (define same-fringe? (lambda (a b) ($equal (tree->stream a) (tree->stream b))))

Natural semantics describe the process of computation in a more structured manner than rewriting semantics. Natural semantics attempts to explain the behavior of an expression through the behavior of its subexpressions. For example:

if e[1] has value v[1] and e[2] has value v[2] and applying v[1] to v[2] gives v[3] ----- then (e[1] e[2]) has value v[3]The parts above the dashed line are called

`e[1], e[2]`

have free variables? We use an environment p to
record bindings of free variables.
A ** judgment** is of the form

`p |- e => v````
which may be
read as "in environment p, expression e evaluates to value v." We
formulate a rule for each form of expression.
```

`Constants`

```
```
-----
p |- #n => n

Since constants have no subexpressions, there are no antecedents. The
line above is often left out.
#### Variables

e(x) = v
--------
p |- x => v

#### Lambda

--------------------------------
p |- (lambda (x) e) => [p, x, e]

Here the object `[p, x, e]`

is a closure.
#### Application

p |- e[1] => [p', x, e] p |- e[2] => v[2] p'[x |-> v] |- e => v[3]
------------------------------------------------------------------------
p |- (e[1] e[2]) => v[3]

We can also have special functions here, such as successor (succ).
p |- e[1] => succ p |- e[2] => n
------------------------------------
p |- (e[1] e[2]) => n+1

A proof that `p |- e => v````
is a tree constructed from these
rules, ending (or rooted) in the judgment
````p |- e => v`

. For
"wrong" expressions like `(succ (lambda (x) x))`

there is
no such tree. For divergent expressions like omega, there is also no tree
(it would be infinite).
#### Begin

p |- e[1] => v ... p |- e[n] => v[n]
----------------------------------------
p |- (begin e[1] ... e[n]) => v[n]

#### Let

p |- e[1] => v[1] p[x |-> v] |- e[2] => v[2]
------------------------------------------------
p |- (let ((x e[1])) e[2]) => v[2]

### Exercise

Construct a proof that `(let ((f (lambda (x) (succ x)))) (begin (f 1) (f 2)))`

evaluates to 3.
What about assignment? To support this we must change the form of judgments
to use and produce a store. Now we have `p, s |- e => v, s[2]`

.
This means "starting with store s, e evaluates to v in environment p and
yields store s[2]." Here are some of the new rules.

p, s |- e[1] => [p', x, e], s[2]
p, s[2] |- e[2] => v[2], s[3]
p'[x |->v], s[3] |- e => v[3], s[4]
----
p, s[1] |- (e[1] e[2]) => v[3], s[4]
p, s[1] |- e => v, s[2] (x in dom(s[2])
----
p, s[1] |- (set! x e) => #f, s[2][x |-> v]

You are now ready to read the dynamic semantics chapters of the definition
of standard ML.
### **Puzzle

Is it possible to describe `let/cc`

using natural semantics?