hash-table-enumerations.lisp 3.71 KB
Newer Older
1
;;;; -*- Mode: Lisp -*-
2

3 4 5
;;;; hash-table-enumerations.lisp --
;;;;
;;;; See file COPYING for copyright and licensing information.
6

7
(in-package "CL.EXTENSIONS.DACF.ENUMERATIONS")
8

9 10 11

;;;;===========================================================================
;;;; Hash Table Enumerations.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

(defclass hash-table-enumeration (enumeration)
  ((keysp :reader keysp :initarg :keys)
   (valuesp :reader valuesp :initarg :values)
   (kv-pairs-p :reader key-value-pairs-p :initarg :key-value-pairs)
   (underlying-enumeration :accessor underlying-enumeration)
   )
  (:documentation "The Hash Table Enumeration Class.")
  (:default-initargs :keys nil :values t :key-value-pairs nil))


(defgeneric hash-table-enumeration-p (x)
  (:method ((x t)) nil)
  (:method ((x hash-table-enumeration)) t))


(defmethod initialize-instance :after ((x hash-table-enumeration)
				       &key
				       keys
				       (values t)
				       (key-value-pairs nil kvp-supplied-p)
				       &allow-other-keys)
  (let ((ht (enumeration-object x)))
    (when (and keys values kvp-supplied-p (not key-value-pairs))
      (cerror "Keys and values will be collected."
              "The enumeration of ~S was asked to supply keys and values, but not key-value pairs.  This is inconsistent."
              ht))
    (setf (underlying-enumeration x)
	  (enumerate (cond ((or (and keys values) key-value-pairs)
			    (loop for k being the hash-key of ht
				  using (hash-value v)
				  when key-value-pairs collect (cons k v)))
                           (keys
			    (loop for k being the hash-key of ht
				  collect k))
			   (values
			    (loop for v being the hash-value of ht
				  collect v)))
                     ))))



(defmethod enumerate ((x hash-table)
		      &key
                      start
                      end
		      keys
                      (values t)
                      key-value-pairs
                      &allow-other-keys)
62 63 64 65 66 67 68 69 70 71 72
  "Calling ENUMERATE on a HASH-TABLE returns a HASH-TABLE-ENUMERATION instance.

If KEYS is true, the HASH-TABLE-ENUMERATION scans the keys of the
underlying HASH-TABLE.  If VALUES is true (the default), the
HASH-TABLE-ENUMERATION scans the values of the underlying HASH-TABLE.
If KEY-VALUE-PAIRS is true, then the HASH-TABLE-ENUMERATION yields
key-values dotted pairs.

Note that it makes no sense to set \"bounds\" on a
HASH-TABLE-ENUMERATION, as an HASH-TABLE is an unordered data
structure.  START and END are ignored."
73 74
  (declare (ignore start end))
  (make-instance 'hash-table-enumeration
75
		 :object x
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
		 :keys keys
		 :values values
		 :key-value-pairs key-value-pairs))


(defmethod has-more-elements-p ((x hash-table-enumeration))
  (has-more-elements-p (underlying-enumeration x)))


(defmethod has-next-p ((x hash-table-enumeration))
  (has-next-p (underlying-enumeration x)))


(defmethod next ((x hash-table-enumeration) &optional default)
  (declare (ignore default))
  (next (underlying-enumeration x)))


(defmethod current ((x hash-table-enumeration) &optional (errorp t) (default nil))
  (cond ((and errorp (not (has-next-p x)))
         (error 'no-such-element :enumeration x))
        ((and (not errorp) (not (has-next-p x)))
         default)
        (t (current (underlying-enumeration x)))))


(defmethod reset ((x hash-table-enumeration))
  (reset (underlying-enumeration x)))


106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
;;; Extra hash-table utilities.

(defun enumerate-keys (ht)
  (declare (type hash-table ht))
  (enumerate ht :keys t :values nil :key-value-pairs nil))


(defun enumerate-values (ht)
  (declare (type hash-table ht))
  (enumerate ht :keys nil :values t :key-value-pairs nil))


(defun enumerate-key-value-pairs (ht)
  (declare (type hash-table ht))
  (enumerate ht :keys nil :values nil :key-value-pairs t))


123
;;;; end of file -- hash-table-enumerations.lisp --