changeset 651: |
af486e0a40c9 |
parent: |
8d7aa0af2367
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Sat, 14 Sep 2024 22:13:06 -0400 |
permissions: |
-rw-r--r-- |
description: |
multi-binaries, working on removing x.lisp |
1 ;;; std/list.lisp --- List utils 6 ;; (reexport-from :sb-int 7 ;; :include '(:recons :memq :assq :ensure-list :proper-list-of-length-p :proper-list-p 10 (defun ensure-car (thing) 11 "If THING is a CONS, its CAR is returned. Otherwise THING is returned." 16 (defun ensure-cons (cons) 17 "If CONS is a cons, it is returned. Otherwise returns a fresh cons with CONS 18 in the car, and NIL in the cdr." 23 (define-modify-macro appendf (&rest lists) append 24 "Modify-macro for APPEND. Appends LISTS to the place designated by the first 27 (define-modify-macro nconcf (&rest lists) nconc 28 "Modify-macro for NCONC. Concatenates LISTS to place designated by the first 31 (define-modify-macro unionf (list &rest args) union 32 "Modify-macro for UNION. Saves the union of LIST and the contents of the 33 place designated by the first argument to the designated place.") 35 (define-modify-macro nunionf (list &rest args) nunion 36 "Modify-macro for NUNION. Saves the union of LIST and the contents of the 37 place designated by the first argument to the designated place. May modify 40 (define-modify-macro reversef () reverse 41 "Modify-macro for REVERSE. Copies and reverses the list stored in the given 42 place and saves back the result into the place.") 44 (define-modify-macro nreversef () nreverse 45 "Modify-macro for NREVERSE. Reverses the list stored in the given place by 46 destructively modifying it and saves back the result into the place.") 48 (declaim (inline delete/swapped-arguments)) 49 (defun delete/swapped-arguments (sequence item &rest keyword-arguments) 50 (apply #'delete item sequence keyword-arguments)) 52 (define-modify-macro deletef (item &rest keyword-arguments) 53 delete/swapped-arguments 54 "Modify-macro for DELETE. Sets place designated by the first argument to 55 the result of calling DELETE with ITEM, place, and the KEYWORD-ARGUMENTS.") 57 (defun let-binding-transform (bs) 60 (cond ((symbolp (car bs)) 65 (error "Bad let bindings"))) 66 (let-binding-transform (cdr bs))))) 68 (defun circular-list (&rest elements) 69 "Creates a circular list of ELEMENTS." 70 (let ((cycle (copy-list elements))) 73 (defun circular-list-p (object) 74 "Returns true if OBJECT is a circular list, NIL otherwise." 76 (do ((fast object (cddr fast)) 77 (slow (cons (car object) (cdr object)) (cdr slow))) 79 (unless (and (consp fast) (listp (cdr fast))) 84 (defun circular-tree-p (object) 85 "Returns true if OBJECT is a circular tree, NIL otherwise." 86 (labels ((circularp (object seen) 88 (do ((fast (cons (car object) (cdr object)) (cddr fast)) 89 (slow object (cdr slow))) 91 (when (or (eq fast slow) (member slow seen)) 92 (return-from circular-tree-p t)) 93 (when (or (not (consp fast)) (not (consp (cdr slow)))) 95 (do ((tail object (cdr tail))) 98 (let ((elt (car tail))) 99 (circularp elt (cons object seen)))))))))) 100 (circularp object nil))) 103 (defun group (source n) 105 (when (zerop n) (error "zero length")) 106 (labels ((rec (source acc) 107 (let ((rest (nthcdr n source))) 113 (cons source acc)))))) 114 (if source (rec source nil) nil))) 116 (eval-when (:compile-toplevel :execute :load-toplevel) 118 (labels ((rec (x acc) 121 ((typep x 'sb-impl::comma) (rec (sb-impl::comma-expr x) acc)) 122 ((atom x) (cons x acc)) 125 (rec (cdr x) acc)))))) 129 ;; Destructive merge of two sorted lists. 130 ;; From Hansen's MS thesis. 131 (defun merge! (a b predicate) 132 (labels ((merge-loop (r a b) 133 (cond ((funcall predicate (car b) (car a)) 137 (merge-loop b a (cdr b)))) 138 (t ; (car a) <= (car b) 142 (merge-loop a (cdr a) b)))))) 145 ((funcall predicate (car b) (car a)) 148 (merge-loop b a (cdr b))) 150 (t ; (car a) <= (car b) 153 (merge-loop a (cdr a) b)) 156 ;; Stable sort procedure which copies the input list and then sorts 157 ;; the new list imperatively. Due to Richard O'Keefe; algorithm 158 ;; attributed to D.H.D. Warren. 159 (defun sort! (seq predicate) 162 (let* ((j (truncate n 2)) 166 (merge! a b predicate))) 171 (setf seq (cddr seq)) 172 (when (funcall predicate y x) 183 (astep (length seq)))) 186 (defun g!-symbol-p (s) 188 (> (length (symbol-name s)) 2) 189 (string= (symbol-name s) 194 (defun o!-symbol-p (s) 196 (> (length (symbol-name s)) 2) 197 (string= (symbol-name s) 202 (defun o!-symbol-to-g!-symbol (s) 204 (subseq (symbol-name s) 2))) 206 (defmacro defmacro/g! (name args &rest body) 207 (let ((syms (remove-duplicates 208 (remove-if-not #'g!-symbol-p 210 (multiple-value-bind (body declarations docstring) 211 (parse-body body :documentation t) 212 `(defmacro ,name ,args 218 `(,s (gensym ,(subseq 224 (defmacro defmacro! (name args &rest body) 225 (let* ((os (remove-if-not #'o!-symbol-p (flatten args))) 226 (gs (mapcar #'o!-symbol-to-g!-symbol os))) 227 (multiple-value-bind (body declarations docstring) 228 (parse-body body :documentation t) 229 `(defmacro/g! ,name ,args 233 `(let ,(mapcar #'list (list ,@gs) (list ,@os)) 236 (defmacro defun! (name args &body body) 237 (let ((syms (remove-duplicates 238 (remove-if-not #'g!-symbol-p 240 (multiple-value-bind (body declarations docstring) 241 (parse-body body :documentation t) 246 (let ,(mapcar (lambda (s) 247 `(,s (gensym ,(subseq (symbol-name s) 253 (defun set-equal (list1 list2 &key (test #'eql) (key nil keyp)) 254 "Returns true if every element of LIST1 matches some element of LIST2 and 255 every element of LIST2 matches some element of LIST1. Otherwise returns false." 256 (let ((keylist1 (if keyp (mapcar key list1) list1)) 257 (keylist2 (if keyp (mapcar key list2) list2))) 258 (and (dolist (elt keylist1 t) 259 (or (member elt keylist2 :test test) 261 (dolist (elt keylist2 t) 262 (or (member elt keylist1 :test test)