src/utilities.lisp: Convert merge candidates to presentation form on the fly.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 3 Aug 2019 13:59:40 +0000 (14:59 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 3 Aug 2019 15:46:20 +0000 (16:46 +0100)
In `inconsistent-merge-error', retain the raw list of candidates, and
the presentation function, rather than requiring the caller to convert
the candidates when constructing the condition object.  This makes the
list considerably more useful to condition handler code.

doc/SYMBOLS
doc/misc.tex
src/utilities.lisp

index 96c79c6..6f230a2 100644 (file)
@@ -2328,6 +2328,7 @@ utilities.lisp
   mappend                                       function
   maybe-print-unreadable-object                 macro
   merge-error-candidates                        generic
+  merge-error-present-function                  generic
   merge-lists                                   function
   sb-mop:method-specializers                    generic
   once-only                                     macro
@@ -2381,6 +2382,8 @@ instance-initargs
   cl:standard-object
 merge-error-candidates
   inconsistent-merge-error
+merge-error-present-function
+  inconsistent-merge-error
 sb-mop:method-specializers
   cl:standard-method
 
index 2d86406..c253630 100644 (file)
@@ -160,12 +160,16 @@ These symbols are defined in the @|sod-utilities| package.
 
 \subsection{Merging lists}
 
-\begin{describe}{cls}{inconsistent-merge-error (error) \&key :candidates}
+\begin{describe}{cls}
+    {inconsistent-merge-error (error) \&key :candidates :present}
 \end{describe}
 
 \begin{describe}{gf}{merge-error-candidates @<error> @> @<list>}
 \end{describe}
 
+\begin{describe}{gf}{merge-error-present-function @<error> @> @<function>}
+\end{describe}
+
 \begin{describe}{fun}
     {merge-lists @<lists> \&key :pick (:test \#'eql) :present @> @<list>}
 \end{describe}
index b02fdf4..4935f8b 100644 (file)
                         (cdddr neigh-record) best-path)))))))
     dead))
 
-(export '(inconsistent-merge-error merge-error-candidates))
+(export '(inconsistent-merge-error
+         merge-error-candidates merge-error-present-function))
 (define-condition inconsistent-merge-error (error)
   ((candidates :initarg :candidates
-              :reader merge-error-candidates))
+              :reader merge-error-candidates)
+   (present :initarg :present :initform #'identity
+           :reader merge-error-present-function))
   (:documentation
    "Reports an inconsistency in the arguments passed to `merge-lists'.")
   (:report (lambda (condition stream)
             (format stream "Merge inconsistency: failed to decide between ~
                             ~{~#[~;~A~;~A and ~A~:;~
                                  ~@{~A, ~#[~;and ~A~]~}~]~}"
-                    (merge-error-candidates condition)))))
+                    (mapcar (merge-error-present-function condition)
+                            (merge-error-candidates condition))))))
 
 (export 'merge-lists)
 (defun merge-lists (lists &key pick (test #'eql) (present #'identity))
                              candidates))
           (winner (cond ((null leasts)
                          (error 'inconsistent-merge-error
-                                :candidates (mapcar present candidates)))
+                                :candidates candidates
+                                :present present))
                         ((null (cdr leasts))
                          (car leasts))
                         (pick