CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
setA
setis a finite stream of strings.
(define-type set
`; A function that takes 0 args and builds either:`
(->
`; an empty set OR an element and the rest of the stream`
(U set-empty set-add)
)
)
*; set-empty denotes the end of the stream, so it has no fields
(struct set-empty ())
*; set-add is akin to stream-add: holds a string and the rest of the stream
(struct set-add ([first : String] [rest : set]))
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
Here is an example of a set $\{"a", "b", "c"\}$
(thunk
(set-add "a"
(thunk
(set-add "b"
(thunk
(set-add "c" (thunk (set-empty))))))))
which is similar to building a list, but with thunks interleaved
(cons "a"
(cons "b"
(cons "c" empty)))
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
(: print-set (-> set Void))
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
(: print-set (-> set Void))
(define (print-set s)
(match (s) ; Call s to build the next element:
[(set-empty) (void)] ; If there are no more elements, void does nothing
[(set-add h l) ; Otherwise,
(displayln h) ; print the element
(print-set l) ; and loop
]
)
)
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
(: copy (-> set set))
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
(: copy (-> set set))
(define (copy l)
(thunk
(match (l)
[(set-empty) (set-empty)]
[(set-add h l)
(set-add h (copy l))
]
)
)
)
(define (copy l)
(match l
[(list) (list)]
[(cons h l)
(cons h (copy l))
]
)
)
Similarly to infinite streams, when building a stream from another, we must
thunkBEFORE wematch.
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
(: faulty-copy-set (-> set set))
(define (faulty-copy-set s)
(match `(s)`
[(set-empty) (`thunk` (set-empty))]
[(set-add h s)
(`thunk` (set-add h (faulty-copy-set s)))]))
(faulty-copy-set s) asks s to build
the first element before building its copy.(faulty-copy-set s) to build its
first element, you are actually requesting s to build its second element.(thunk ...) must surround any (match (s) ...)CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
stream-foldStream-fold behaves like the following function, which returns a list of the updates to the accumulator. Use this function as the blueprint to your solution.
(define (fold2 f a l)
(match l
[(list) (list)]
[(cons h l)
; h = e1
; l = [e2, e3]
; a1 = f e1 a
(define a1 (f h a))
(displayln a1)
(define result (fold2 f a1 l))
; result = [a1, a2, a3]
(cons a result)
; expected output: [a, f e1 a, f e2 (f e1 a), f e3 (f e2 (f e1 a))]
]))
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
Our goal is to implement an evaluation function that takes an expression and yields a value.
expression = value | variable | function-call
value = number
function-call = ( expression+ )
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
expression = value | variable | function-call
How do we evaluate a value?
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
expression = value | variable | function-call
How do we evaluate a value? The evaluation of a value
visvitself.
(check-equal? 10 (eval-exp (r:number 10)))
How do we evaluate a function call?
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
expression = value | variable | function-call
How do we evaluate a value? The evaluation of a value
visvitself.
(check-equal? 10 (eval-exp (r:number 10)))
How do we evaluate a function call? The evaluation of a function call evaluates each expression from left to right and then it applies the function to the arguments.
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
How do we evaluate a function call? The evaluation of a function call evaluates each expression from left to right and then it applies the function to the arguments.
(eval-exp
`'(-`
`(+ 3 2)`
`(* 5 2))` )
①
<- evaluate '-
<- evaluate '(+ 3 2)
<- evaluate '(* 5 2)
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
How do we evaluate a function call? The evaluation of a function call evaluates each expression from left to right and then it applies the function to the arguments.
(eval-exp
`'(-`
`(+ 3 2)`
`(* 5 2))` )
①
<- evaluate '-
<- evaluate '(+ 3 2)
<- evaluate '(* 5 2)
= ((eval-exp `'-`)
`(eval-exp` '(+ 3 2))
`(eval-exp` '(* 5 2)))
②
<- evaluate `'+`, evaluate `3`, evaluate `2`
<- evaluate `'*`, evaluate `5`, evaluate `2`
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
How do we evaluate a function call? The evaluation of a function call evaluates each expression from left to right and then it applies the function to the arguments.
(eval-exp
`'(-`
`(+ 3 2)`
`(* 5 2))` )
①
<- evaluate '-
<- evaluate '(+ 3 2)
<- evaluate '(* 5 2)
= ((eval-exp `'-`)
`(eval-exp` '(+ 3 2))
`(eval-exp` '(* 5 2)))
②
<- evaluate `'+`, evaluate `3`, evaluate `2`
<- evaluate `'*`, evaluate `5`, evaluate `2`
= ((eval-exp '-)
(`(eval-exp '+)` 3 2)
(`(eval-exp '*)` 5 2))
③
<- numbers are values, so just return those
<- numbers are values, so just return those
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
= (`(eval-exp '-)`
(`(eval-exp '+)` 3 2)
(`(eval-exp '*)` 5 2))
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
= (`(eval-exp '-)`
(`(eval-exp '+)` 3 2)
(`(eval-exp '*)` 5 2))
<- Evaluate '- as function -
<- Evaluate '+ as function +
<- Evaluate '* as function *
= (-
(+ 3 2)
(* 5 2))
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
Essentially evaluating an expression translates our AST nodes as a Racket expression.
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
eval-exp(check-equal? (r:eval-exp (r:number 5)) 5)
(check-equal? (r:eval-exp (r:number 10)) 10)
(check-equal? (r:eval-exp (r:variable '+)) +)
(check-equal?
(r:eval-exp
(r:apply
(r:variable '+)
(list (r:number 10) (r:number 5))))
15)
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
eval-expWe are using the AST as structs, not datums. Assume function calls are binary.
(: r:eval-exp (-> r:expression Number))
(define (r:eval-exp exp)
(match exp
; If it's a number, return that number
[(r:number v) v]
; If it's a function with 2 arguments
[(r:apply (r:variable f) (list arg1 arg2))
(define func (r:eval-builtin f))
(func (r:eval-exp arg1) (r:eval-exp arg2))
]
)
)
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
r:eval-builtin(check-equal? (r:eval-builtin '+) +)
(check-equal? (r:eval-builtin '-) -)
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
r:eval-builtin(check-equal? (r:eval-builtin '+) +)
(check-equal? (r:eval-builtin '-) -)
(define (r:eval-builtin sym)
(cond [(equal? sym '+) +]
[(equal? sym '-) -]
[(equal? sym '*) *]))
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
applyFunction (apply f args) applies function f to the list of arguments args.
(check-equal? (apply + (list 1 2 3 4)) 10)
Example: implement
(sum l)that returns the summation of all members inlusingapply.
(check-equal? (sum (list)) 0)
(check-equal? (sum (list 1 2 3 4)) 10)
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
applyFunction (apply f args) applies function f to the list of arguments args.
(check-equal? (apply + (list 1 2 3 4)) 10)
Example: implement
(sum l)that returns the summation of all members inlusingapply.
(check-equal? (sum (list)) 0)
(check-equal? (sum (list 1 2 3 4)) 10)
(define (sum l) (apply + l))
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
Some multi-arg operations can be implemented without the need of
apply.
Implement (sum l) without using apply.
(check-equal? (sum (list)) 0)
(check-equal? (sum (list 1 2 3 4)) 10)
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
Some multi-arg operations can be implemented without the need of
apply.
Implement (sum l) without using apply.
(check-equal? (sum (list)) 0)
(check-equal? (sum (list 1 2 3 4)) 10)
(define (sum l)
(cond
[(empty? l) 0]
[else (+ (first l) (sum (rest l)))]))
CS450 ☽ Finite-streams, evaluating expressions ☽ Lecture 12 ☽ Tiago Cogumbreiro
How could we implement a function with multiple parameters, similar to
+? Use the.notation.
. notation declares that the next variable represents a list of zero or more parameters.(define (map-ex f . args)
(map f args))
(check-equal? (list 2 3 4) (map-ex (curry + 1) 1 2 3))
(define (sum . l) (foldl + 0 l))
(check-equal? 6 (sum 1 2 3))