;; CSE 341 - sample solution to Mini Exercise #2 ;; structs, representing objects, lexical scoping, and macros. #lang racket ;; Question 1 - recursive flip (define (flip xs) (if (null? xs) null (cons (not (car xs)) (flip (cdr xs))))) ;; Question 2 - flip using map (define (mflip xs) (map not xs)) ;; Question 3 - map2 function ;; If one of the lists is shorter than the other, we call the error function ;; (matching what the built-in Racket map function does). A more forgiving ;; alternative would be to just use the number of elements from the shorter list. (define (map2 f s1 s2) (cond [(and (null? s1) (null? s2)) '()] [(or (null? s1) (null? s2)) (error "lists provided to map2 are different lengths")] [else (cons (f (car s1) (car s2)) (map2 f (cdr s1) (cdr s2)))])) ;; to try: (map2 + '(1 2 3) '(10 11 12)) ;; (map2 + '(1 2 3 4) '(100 200)) -- WILL GIVE AN ERROR (map2 (lambda (x y) (+ x y 10)) '(1 2 3) '(10 11 12)) ;; Question 4 (let ([x 2]) (let ([f (lambda (n) (+ x n))]) (let ([x 17]) (f 3)))) ;; this evaluates to 5 ;; (f 3) is evaluated in an environment with f bound to ;; the lambda, and x bound to 17 (overriding the x=2 binding) ;; the lambda captures its environment of definition, so when the ;; body is evaluated n is bound to 3, and x is bound to 2 ;; Question 5 (define (addN n) (lambda (m) (+ m n))) (let* ([m 10] [n 20] [addit (addN 3)]) (addit 100)) ;; the let* evaluates to 103 ;; addit is bound to a lambda. The lambda captures its environment of ;; definition, so that n=3. Then we call (addit 100). This evaluates ;; the lambda with m bound to 100, so we get a value of 103. The ;; (m 10) and (n 20) bindings have no effect. ;; Question 6 (let ([f (lambda () (/ 1 0))] [x (+ 3 4)]) (+ x x)) ;; this evaluates to 14 -- note that we never call f, so we never evaluate the divide by 0 ;; Question 7 - point3d struct (struct point3d (x y z) #:transparent #:mutable) (define p (point3d 0 0 0)) (set-point3d-z! p 10) (display "Question 5 result: ") (print p) (newline) (newline) ;; Question 8 - simulated cell class ;; each simulated instance of cell has its own value (define (make-cell) (let ([value null]) (define (get-value) value) (define (set-value! n) (set! value n)) (define (dispatch m) (cond [(eq? m 'get-value) get-value] [(eq? m 'set-value!) set-value!] [else (error "Unknown request -- MAKE-CELL" m)])) dispatch)) ;; some expressions to try: ;; (define c (make-cell)) ;; ((c 'get-value)) ;; ((c 'set-value!) "octopus") ;; ((c 'get-value!)) ;; Question 9 - simulated point class ;; each simulated instance of point has its own x and y (define (make-point) (let ([x 0] [y 0]) (define (get-x) x) (define (get-y) y) (define (set-x! new-x) (set! x new-x)) (define (set-y! new-y) (set! y new-y)) (define (print-point) (display "point x=") (display x) (display " y=") (display y)) (define (dispatch m) (cond [(eq? m 'get-x) get-x] [(eq? m 'get-y) get-y] [(eq? m 'set-x!) set-x!] [(eq? m 'set-y!) set-y!] [(eq? m 'print-point) print-point] [else (error "Unknown request -- MAKE-POINT" m)])) dispatch)) ;; some expressions to try: ;; (define q (make-point)) ;; ((q 'get-x)) ;; ((q 'set-x!) 100) ;; ((q 'print-point)) ;; Question 10 ;; this time we don't have the problems of possible multiple ;; evaluations that we have with "or" (define-syntax and2 (syntax-rules () [(and2 a b) (if a b #f)])) ;; examples (and2 (> 1 10) (/ 1 0)) (and2 #t "squid") ; paste this in the interaction pane to see how it expands: ; (syntax->datum (expand-once '(and2 (> 1 10) (/ 1 0)))) ;; Question 11 (define-syntax grump (syntax-rules () [(grump x) "no"]))