;; -*- mode:common-lisp; package: mma; -*- (provide 'ucons1) (eval-when (eval compile load) (proclaim '(optimize (speed 3)(safety 0)(debug 0)))) ;; (c) 2011 Richard J. Fateman (in-package :mma) ;; non-standard hash table feature used below (defun eq-hash (object) object) (defvar *uniq-table* (make-hash-table :test 'equal :hash-function #'eq-hash)) (defvar *uniq-atom-table* (make-hash-table :test #'eql)) (defun uniq (x) "Return a canonical representation that is EQUAL to x, such that (equal x y) => (eq (uniq x) (uniq y))" (typecase x ((or fixnum symbol) x) (atom (or (gethash x *uniq-atom-table*) (setf (gethash x *uniq-atom-table*) x))) (cons (ucons (uniq (car x)) ; this could check in ; *uniq-table* first... (uniq (cdr x)))))) (defvar *fakecons* '(car . cdr)) (defun ucons (x y) "Unique cons: (eq (ucons x y) (ucons x y)) is always true." (declare (special *fakecons* *uniq-table*) (optimize (speed 3)(safety 0)(debug 0))) (let((temp *fakecons*)(tt *uniq-table*)) (setf (car temp) x (cdr temp) y) ;don't allocate yet. (cond ((gethash temp tt)) ;;If already there, great. (t (setf (gethash temp tt) temp) (setf *fakecons* (cons 'car 'cdr)) temp)))) (defun umapcar(f x)(cond((null x)nil) (t (ucons (funcall f (car x))(umapcar f (cdr x)))))) (defmacro ulist(&rest l)(cond ((null l)nil) (t `(ucons ,(car l) (ulist ,@(cdr l)))))) (defun uappend(r s)(cond ((null r)s) (t (ucons (car r)(uappend (cdr r) s)))))