Referencing the name of a type (that is, a symbol) in code means that delivery cannot remove that type even if it is not used anywhere else. This is often seen in code using typep, typecase or subtypep to discriminate between types.
For example, if you have code like this:
(defun foo (x) (cond ((typep x 'class1) ...) ((typep x 'class2) ...) ... ((subtypep x 'class1000) ...)))
then delivery would keep all of the classes class1
,...
,class1000
even if nothing else references these classes.
Possible solutions are described in 14.7.1 Referencing types via methods and 14.7.2 Referencing types via predicates.
Code can reference type names either directly as shown in 14.7 Avoid referencing type names or via type-of in code like this:
(defun foo (x) (let ((type (type-of x))) (cond ((eq type 'class1) ...) ((eq type 'class2) ...) ... ((eq type 'class1000) ...))))
Instead, you could express the conditional clauses as methods specialized for each class:
(defmethod foo ((x class1)) ...) (defmethod foo ((x class2)) ...) ... (defmethod foo ((x class1000)) ...)
This would allow any unused classes to be removed by delivery, because each method is a separate function.
If you do not wish to retain CLOS, and are referencing types that have built-in predicates, or structure types, you could use these predicates instead of the type names to allow delivery to remove unused types. For example this code:
(typecase x (integer (process-an-integer x)) (string (process-a-string x)) (a-struct (process-a-struct x)))
could be rewritten as:
(cond ((integerp x) (process-an-integer x)) ((stringp x) (process-a-string x)) ((a-struct-p x) (process-a-struct x)))
Delivery User Guide - 01 Dec 2021 19:35:06