#+SBCL (DECLAIM (SB-EXT:MUFFLE-CONDITIONS CL:STYLE-WARNING)) (let ((globals (make-hash-table))) (defun isa (name type) (setf (gethash name globals) (make-instance type :name name))) (defmethod zap () (maphash #'(lambda (k v) (declare (ignore k)) (setf (cached-value v) nil)) globals)) (defun one (s) (gethash s globals (one-error s))) ) (defun one-error (s) (error "no cached value for ~a" s)) (defclass cached () ((name :accessor cached-name :initarg :name :initform (gensym "cached")) (value :accessor cached-value :initarg :value :initform nil))) (defmethod ! ((s null) ) (error "missing cached value")) (defmethod ! ((s symbol )) (! (one s))) (defmethod ! ((s string )) (! (one s))) (defmethod ! ((c cached)) (or (cached-value c) (setf (cached-value c) (? c)))) (defmethod ? ((c cached)) (format t "missing method")) (defmethod ? ((o oneof)) (let* ((l (all o)) (n (length l))) (elt l (random n)))) (defclass ranged (cached) nil) (defmethod ? ((r ranged)) (+ (from r) (* (/ (random 1000) 1000) (- (to r) (from r))))) (defmethod from ((r ranged)) 0) (defmethod to ((r ranged)) 1) (defclass oneof (cached) nil) (defmethod all ((o oneof) ) nil) ;;;; short cuts (defmacro defnum (what (from to) &body filter) (let ((filter1 (or filter `(call-next-method)))) `(progn (defclass ,what (ranged) nil) (defmethod from ((x ,what)) ,from) (defmethod to ((x ,what)) ,to) (defmethod ? :around ((it ,what)) ,@filter1)))) (defmacro defone (what (&rest range)) `(progn (defclass ,what (oneof) nil) (defmethod all ((x ,what)) ',range))) ;;;; examples (defnum posreal (0 most-positive-fixnum) (* 1.0 (call-next-method))) (defnum posint (0 most-positive-fixnum) (round (call-next-method))) (defone weekdays (sun mon tues wed thurs fri sat)) (defone bool (t f)) ;;;; demo (defun demo1 () (let ((names '(weekday posint posreal bool))) (dolist (name names) (isa name name)) (dotimes (i 2) (dolist (one names) (format t "~a) ~a = ~a~%" i one (! one)))) (zap) (dotimes (i 2) g (dolist (one names) (format t "~a) ~a = ~a~%" i one (! one)))) ))