Branch
Hash :
fbffe9ff
Author :
Thomas de Grivel
Date :
2023-07-11T13:59:44
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
;; cl-compare - generic comparison functions
;; Copyright 2022,2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
;; are included in all copies and substantial portions of this
;; software.
;;
;; THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
;; PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
;; AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
;; THIS SOFTWARE.
(defpackage :compare
(:use :cl)
(:export #:compare))
(in-package :compare)
(defvar *types-order*
(list 'null
'character
'number
'package
'symbol
'string
'vector
'pathname))
(defgeneric compare (a b))
(defun princ-compare (a b)
(compare (princ-to-string a) (princ-to-string b)))
(defmethod compare (a b)
(dolist (type *types-order*)
(let ((ta (typep a type))
(tb (typep b type)))
(cond ((and ta tb)
(princ-compare a b))
((not ta) (return-from compare -1))
((not tb) (return-from compare 1)))))
(princ-compare a b))
(defmethod compare ((a number) (b number))
(cond ((< a b) -1)
((= a b) 0)
(t 1)))
(defmethod compare ((a package) (b package))
(compare (package-name a)
(package-name b)))
(defmethod compare ((a symbol) (b symbol))
(ecase (compare (symbol-package a) (symbol-package b))
(-1 -1)
(1 1)
(0 (compare (symbol-name a) (symbol-name b)))))
(defmethod compare ((a string) (b string))
(cond ((eq a b) 0)
((string< a b) -1)
((string= a b) 0)
(t 1)))
(defmethod compare ((a null) (b string))
-1)
(defmethod compare ((a string) (b null))
1)
(defmethod compare ((a cons) (b cons))
(ecase (compare (car a) (car b))
(-1 -1)
(1 1)
(0 (compare (cdr a) (cdr b)))))
(defmethod compare ((a vector) (b vector))
(let ((len-a (length a))
(len-b (length b)))
(dotimes (i (min len-a len-b))
(let ((ai (elt a i))
(bi (elt b i)))
(ecase (compare ai bi)
(-1 (return-from compare -1))
(1 (return-from compare 1))
(0 nil))))
(compare len-a len-b)))
(defun pathname-string (p)
(declare (type pathname p))
(with-output-to-string (s)
(print-object p s)))
(defmethod compare ((a pathname) (b pathname))
(compare (pathname-string a) (pathname-string b)))