;;;Exercises from chapter 13 of 'Common Lisp Interactive Approach' ;;;Set up package for this file and its functions. (eval-when (:compile-toplevel :load-toplevel :execute) (if (not (find-package "UTIL")) ;;Symbol names MUST be upper-case to work properly (defpackage "UTIL" (:use "COMMON-LISP") ;;(shadow "symbol") (:export "ELEMENTP" "ELEMENT" "BAGP" "BAG" )) (export '(ELEMENTP ELEMENT BAGP BAG) :util) )) (in-package "UTIL") ;;;Determine if argument meets the criteria of an 'element' as given in '13.12' (defun elementp (e) (cond ((symbolp e) t) ((characterp e) t) ((numberp e) t) ((packagep e) t) )) ;;;Added definition from ch17.11 (deftype element () "Elements are objects testable by EQL, namely symbols, characters, numbers, and packages." '(satisfies util:elementp)) ;;;Helper function to visit list members searching for duplicate elements ;;;This turns out to be unnecessary (defun list-dup-el-srch (n e l) "Returns true if list has duplicate elements, otherwise nil" (check-type e element) (block b (progn (if (and (< n 0) (null l)) (return-from b nil)) (loop for i from 0 to (1- n) when (eql e (elt l i)) do (return-from b t)) (list-dup-el-srch (1- n) (first l) (rest l)) ))) ;;;Added function from ch17:15 (defun bagp (l) "Return true if L is a BAG (a list with at least one duplicate element) otherwise nil" ;;Decided not to make a bag have mandatory element duplication ;;because then simple lists cannot be sets ;;(check-type l list) ;;(list-dup-el-srch (1- (length l)) (first l) (rest l)) (if (listp l) t) ) ;;;Added function from ch17:15 (deftype bag () "Bags are lists with at least one duplicated element" '(satisfies bagp))