45 lines
1.3 KiB
Common Lisp
45 lines
1.3 KiB
Common Lisp
;; Owl Lisp, though a dialect of Scheme, has no true variables: it has
|
|
;; only value-bindings. We cannot use "make-parameter" to specify an
|
|
;; optional modulus. Instead let us introduce a new type for modular
|
|
;; integers.
|
|
|
|
(define (modular? x)
|
|
;; The new type is simply a pair of integers.
|
|
(and (pair? x) (integer? (car x)) (integer? (cdr x))))
|
|
|
|
(define (enhanced-op op)
|
|
(lambda (x y)
|
|
(if (modular? x)
|
|
(if (modular? y)
|
|
(begin
|
|
(unless (= (cdr x) (cdr y))
|
|
(error "mismatched moduli"))
|
|
(cons (floor-remainder (op (car x) (car y)) (cdr x))
|
|
(cdr x)))
|
|
(cons (floor-remainder (op (car x) y) (cdr x))
|
|
(cdr x)))
|
|
(if (modular? y)
|
|
(cons (floor-remainder (op x (car y)) (cdr y))
|
|
(cdr y))
|
|
(op x y)))))
|
|
|
|
(define enhanced+ (enhanced-op +))
|
|
(define enhanced-expt (enhanced-op expt))
|
|
|
|
(define (f x)
|
|
;; Temporarily redefine + and expt so they can handle either regular
|
|
;; numbers or modular integers.
|
|
(let ((+ enhanced+)
|
|
(expt enhanced-expt))
|
|
;; Here is a definition of f(x), in the notation of Owl Lisp:
|
|
(+ (+ (expt x 100) x) 1)))
|
|
|
|
;; Use f on regular integers.
|
|
(display "No modulus: ")
|
|
(display (f 10))
|
|
(newline)
|
|
|
|
(display "modulus 13: ")
|
|
(display (car (f (cons 10 13))))
|
|
(newline)
|