I've written, as part of the random type prop tester, a generic function named make-random-type-containing that takes a single argument and produces a random type to which that object belongs. Right now it makes awkward use of call-next-method to link together methods for classes of increasing generality, but it's hard to make the probabilities come out right, particularly as new methods are added.
I've realized I should instead have defined this method combination:
(defun car-is-positive-integer (x) (typep (car x) '(integer 1)))(define-method-combination randomized nil ((method-list car-is-positive-integer)) (assert method-list) (let* ((qualifiers (mapcar #'method-qualifiers method-list)) (weights (mapcar #'car qualifiers)) (clauses (mapcar #'(lambda (weight method) `(,weight (call-method ,method))) weights method-list))) `(loop (catch 'fail (return (rcase ,@clauses))))))
What this does is use integer method qualifiers as weights. A method is chosen with probability proportional to its weight (by the macro rcase, not here defined). The catch allows methods to abort by throwing to fail; when that happens another method is selected at random.
