# Example Solution for Assignment 2 by dxr20321

VIEWS: 45 PAGES: 18

• pg 1
```									Example Solution
for
Assignment 2

Prof. Dr. Mira Mezini
MSc. Vaidas Gasiunas
Dipl.-Inform. Karl Klose
Software Technology

Group &
Aspect-Oriented
Programming

• Write a function fib-even that takes an argument and
returns a list of all even fibonacci numbers less than the n-
th fibonacci number (again, fibonacci numbers are indexed
starting with 0). The list should be sorted in increasing
order (see test cases).

(test (fib-even 2) empty)
(test (fib-even 3) (list 2))
(test (fib-even 4) (list 2))
(test (fib-even 6) (list 2 8))
(test (fib-even 30)
(list 2 8 34 144 610 2584 10946 46368 196418
832040))

2
Software Technology

Group &
Aspect-Oriented
Programming

(define (fib n)
(if (< n 2)
1
(+ (fib (- n 1)) (fib (- n 2)))))

(define (fib-even n)
(if (< n 3) empty
(let ( (x (fib (- n 1)))
(fl (fib-even (- n 1))))
(if (even? x) (append fl (list x)) fl)))))

3
Software Technology

Group &
Aspect-Oriented
Programming

(define (fiblist n)
(if (< n 1) empty
if (= n 1) (list 1)
(if (= n 2) (list 1 1)
(let ((rest (fiblist (- n 1))))
(let ((nextfib (+ (first rest) (second rest))))
(cons nextfib rest)))))))

(define (fib-even n)
(reverse (filter even? (fiblist n))))

4
Software Technology

Group &
Aspect-Oriented
Programming

•         Extend the language F1WAE with an if0 expression:
(if0 (cond F1WAE?) (then F1WAE?) (else F1WAE?))

•         The new expression type should have the following semantics:
– If cond == 0 the then part will be evaluated.
– Otherwise, the else part will be evaluated

5
Software Technology

Group &
Aspect-Oriented
Programming

; AST for expressions of F1WAE
(define-type F1WAE
[num (n number?)]
[sub (lhs F1WAE?) (rhs F1WAE?)]
[if0 (cond F1WAE?) (then F1WAE?) (else F1WAE?)]
[with (name symbol?) (named-expr F1WAE?)
(body F1WAE?)]
[id (name symbol?)]
[app (fun-name symbol?) (arg F1WAE?)])

6
Software Technology

Group &
Aspect-Oriented
Programming

;; parse: s-expr -> F1WAE
;; to convert s-expressions into F1WAE values
(define (parse s-expr)
(cond
[(number? s-expr) (num s-expr)]
[(symbol? s-expr) (id s-expr)]
[(list? s-expr)
(case (first s-expr)
(parse (third s-expr)))]
[(-) (sub (parse (second s-expr))
(parse (third s-expr)))]
[(with)
(local
((define sec (second s-expr)))
(with (first sec) (parse (second sec))
(parse (third s-expr))))]
[(if0) (if0 (parse (second s-expr))
(parse (third s-expr))
(parse (fourth s-expr)))]
[else (app (first s-expr)
(parse (second s-expr)))])]))
7
Software Technology

Group &
Aspect-Oriented
Programming

;; interp: F1WAE listof(FunDef) -> number
;; evaluates F1WAE expressions by reducing them to their
corresponding values

(define (interp expr fun-defs sub-rep)
(type-case F1WAE expr
[num (n) n]
[sub (l r) ... ]
[if0 (cond then else)
(if (zero? (interp cond fun-defs sub-rep))
(interp then fun-defs sub-rep)
(interp else fun-defs sub-rep))]
[with (bound-id named-expr bound-body)
...]
[id (name) ...]
[app (fun-name arg-expr)
...]))

8
Software Technology

Group &
Aspect-Oriented
Programming

; AST for expressions of F1WAE
(define-type F1WAE
[num (n number?)]
[sub (lhs F1WAE?) (rhs F1WAE?)]
[if0 (cond F1WAE?) (then F1WAE?) (else F1WAE?)]
[with (name symbol?)
(named-expr F1WAE?)
(body F1WAE?)]
[id (name symbol?)]
[app (fun-name symbol?) (arg F1WAE?)])

9
Software Technology

Group &
Aspect-Oriented
Programming

• Implement a function that computes the n-th fibonacci
number in the extended language by using recursion.

(define fun-defs (list
(fundef 'fib 'n
(parse '{if0 n
1
{if0 {- n 1}
1
{+ {fib {- n 1}} {fib {- n 2}}}}}
))))

(test (evaluate '{fib 5} fun-defs) 8)
(test (evaluate '{fib 6} fun-defs) 13)

10
Software Technology

Group &
Aspect-Oriented
Programming

• Can you define the function if0 in Scheme?
• Let’s try it:

(define (if0 cond then else)
(if (= cond 0) then else))

• Works well for simple test cases
• But what happens when we use it in recursive definitions?

(define (fak n)
(if0 n 1 (* n (fak (- n 1))))

11
Software Technology

Group &
Aspect-Oriented
Programming

• Scheme uses eager evaluation:
Arguments are evaluated before the function body is
evaluated
• Our definition (via interpreter) of if0 uses lazy evaluation:
then and else are only evaluated if cond evaluates to
true and false, respectively

;; interp: F1WAE listof(FunDef) -> number
(define (interp expr fun-defs sub-rep)
(type-case F1WAE expr
...
[if0 (cond then else)
(if (zero? (interp cond fun-defs sub-rep))
(interp then fun-defs sub-rep)
(interp else fun-defs sub-rep))]
...

12
Software Technology

Group &
Aspect-Oriented
Programming

• Extend the interpreter given below so that it uses hash-
tables for representing the environment in order to obtain
an interpreter that runs in less than O(n^2) time. The
resulting interpreter should implement static scoping.

; In short, hash-tables can be used like
; this in Scheme:

; (make-hash-table)
; (hash-table-put! table key value)
; (hash-table-get table key)

(define (hash-table-get-default table name default)
(hash-table-get table name (lambda () default)))

13
Software Technology

Group &
Aspect-Oriented
Programming

; AST for expressions of F1WAE
(define-type F1WAE
[num (n number?)]
[sub (lhs F1WAE?) (rhs F1WAE?)]
[with (name symbol?)
(named-expr F1WAE?)
(body F1WAE?)]
[id (name symbol?)]
[app (fun-name symbol?) (arg F1WAE?)])

;; lookup: symbol environment --> number
(define (lookup name env)
(hash-table-get env name))

14
Software Technology

Group &
Aspect-Oriented
Programming

;; interp: F1WAE listof(FunDef) -> number
(define (interp expr fun-defs sub-rep)
(type-case F1WAE expr
...
[app (fun-name arg-expr)
(let ((the-fun-def (lookup-fundef fun-name fun-defs))
(new-sub-rep (make-hash-table)))
(hash-table-put!
new-sub-rep
(fundef-arg-name the-fun-def)
(interp arg-expr fun-defs sub-rep))
(interp
(fundef-body the-fun-def)
fun-defs
new-sub-rep))]
... ))

15
Software Technology
Group &
Aspect-Oriented
Programming

;; interp: F1WAE listof(FunDef) -> number
(define (interp expr fun-defs sub-rep)
(type-case F1WAE expr
...
[with (bound-id named-expr bound-body)
(let ((oldval
(hash-table-get-default sub-rep bound-id #f)))
(hash-table-put!
sub-rep
bound-id
(interp named-expr fun-defs sub-rep))
(let ((result (interp bound-body fun-defs sub-rep)))
(if (equal? oldval #f)
(hash-table-remove! sub-rep bound-id)
(hash-table-put! sub-rep bound-id oldval))
resul))]

... ))

16
Software Technology
Group &
Aspect-Oriented
Programming
Task 2.3: with Binding - Variant
• Instead of keeping the old value, we store it in the hash
table as a list

(define (bind name value env)
(hash-table-put!
env
name
(cons
value
(hash-table-get-default env name empty))))

(define (unbind name env)
(hash-table-put!
env
name
(rest (hash-table-get env name))))

17
Software Technology
Group &
Aspect-Oriented
Programming
Task 2.3: with Binding - Variant
• Instead of keeping the old value, we store it in the hash
table as a list

;; interp: F1WAE listof(FunDef) -> number
(define (interp expr fun-defs sub-rep)
(type-case F1WAE expr
...
[with (bound-id named-expr bound-body)
(bind bound-id
(interp named-expr fun-defs sub-rep)
sub-rep)
(let ((result (interp bound-body fun-defs sub-rep)))
(unbind bound-id sub-rep)
result)]
... ))

18

```
To top