#lang racket ;; CSE 341 Fall 2011, Lecture 24 ;; Abstraction with dynamic types ;; This is one of several files. This file implements ;; rational numbers using a Racket module. ;; See lec24_non_modules.rkt for the invariants ;; we maintain and the connection to lecture 12 (SML). ;; default is private: have to export things with provide ;; (This explains our bad-style use of (all-provided-out) ;; in earlier letures.) (provide make-frac add print-rat) ;; we can choose to export some of the struct's functions -- ;; the constructor or mutators (if we used them) could ;; allow violating invariants, but we choose to also hide ;; the accessors (provide rat?) ;; there are also nice features for namespace management, e.g., ;; we could rename all our exports ;; (and can provide the same internal binding with different external names) (provide (rename-out (make-frac rat-make) (add rat-add) (rat? is-rat?))) (struct rat (num den)) ;; could make #mutable internally if wanted to (define (gcd x y) (cond [(= x y) x] [(< x y) (gcd x (- y x))] [#t (gcd y x)])) (define (reduce x y) (if (= x 0) (rat 0 1) (let ([d (gcd (abs x) y)]) (rat (quotient x d) (quotient y d))))) (define (make-frac x y) (cond [(= y 0) (error "make-frac: 0 denominator")] [(< y 0) (reduce (- x) (- y))] [#t (reduce x y)])) (define (add r1 r2) (check-rat r1) (check-rat r2) (let ([a (rat-num r1)][b (rat-den r1)] [c (rat-num r2)][d (rat-den r2)]) (reduce (+ (* a d) (* b c))(* b d)))) (define (print-rat r) (check-rat r) (write (rat-num r)) (unless (or (= (rat-num r) 0) (= (rat-den r) 1)) (write '/) (write (rat-den r)))) (define (check-rat r) (unless (rat? r) (error "non-rational provided")))