;;; We start by defining accessors for associations USER(1): (defun assoc-key (assoc) (car assoc)) ASSOC-KEY USER(2): (defun assoc-values (assoc) (cdr assoc)) ASSOC-VALUES ;;; Here is an association that we can ;;; use to test our code. USER(5): (setf *assoc* (make-assoc :key 'test :values '(v1 v2))) (TEST (V1 V2)) ;;; The first accessor works fine USER(8): (assoc-key *assoc*) TEST ;;; The second accessor does not: note ;;; the extra pair of parens. The VALUES ;;; field is supposed to be a list of SYMBOLS. ;;; This is a list that *contains* a list of ;;; symbols. USER(9): (assoc-values *assoc*) ((V1 V2)) ;;; The problem is taking the CDR of the list ;;; where we really wanted the second element. ;;; We fix the problem, and all is well. USER(10): (cdr '(a b c)) (B C) USER(11): (defun assoc-key (assoc) (first assoc)) (defun assoc-values (assoc) (second assoc)) ASSOC-KEY USER(12): USER(12): ASSOC-VALUES USER(13): USER(13): (assoc-values *assoc*) (V1 V2) ;;; We are now building the equality tester ;;; for associations, and need to compare ;;; whether the two symbol lists are equal. ;;; EQ doesn't work for this because they ;;; don't share CONS cells. USER(14): (eq '(a b c) '(a b c)) NIL ;;; To test nested lists of symbols, ;;; characters, and integers, the correct ;;; test is EQUAL. USER(16): (equal '(1 2) '(1 2)) T ;;; Be careful about numbers though. USER(18): (equal '(1.0 2) '(1 2)) NIL USER(19): (eql 1.0 1) NIL ;;; EQUAL more generally works on "sequences" ;;; which means that it's the proper comparator ;;; for strings too. USER(20): (equal "abc" "abc") T