101 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
			
		
		
	
	
			101 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
| (in-package :alexandria)
 | |
| 
 | |
| (defmacro ensure-gethash (key hash-table &optional default)
 | |
|   "Like GETHASH, but if KEY is not found in the HASH-TABLE saves the DEFAULT
 | |
| under key before returning it. Secondary return value is true if key was
 | |
| already in the table."
 | |
|   (once-only (key hash-table)
 | |
|     (with-unique-names (value presentp)
 | |
|       `(multiple-value-bind (,value ,presentp) (gethash ,key ,hash-table)
 | |
|          (if ,presentp
 | |
|              (values ,value ,presentp)
 | |
|              (values (setf (gethash ,key ,hash-table) ,default) nil))))))
 | |
| 
 | |
| (defun copy-hash-table (table &key key test size
 | |
|                                    rehash-size rehash-threshold)
 | |
|   "Returns a copy of hash table TABLE, with the same keys and values
 | |
| as the TABLE. The copy has the same properties as the original, unless
 | |
| overridden by the keyword arguments.
 | |
| 
 | |
| Before each of the original values is set into the new hash-table, KEY
 | |
| is invoked on the value. As KEY defaults to CL:IDENTITY, a shallow
 | |
| copy is returned by default."
 | |
|   (setf key (or key 'identity))
 | |
|   (setf test (or test (hash-table-test table)))
 | |
|   (setf size (or size (hash-table-size table)))
 | |
|   (setf rehash-size (or rehash-size (hash-table-rehash-size table)))
 | |
|   (setf rehash-threshold (or rehash-threshold (hash-table-rehash-threshold table)))
 | |
|   (let ((copy (make-hash-table :test test :size size
 | |
|                                :rehash-size rehash-size
 | |
|                                :rehash-threshold rehash-threshold)))
 | |
|     (maphash (lambda (k v)
 | |
|                (setf (gethash k copy) (funcall key v)))
 | |
|              table)
 | |
|     copy))
 | |
| 
 | |
| (declaim (inline maphash-keys))
 | |
| (defun maphash-keys (function table)
 | |
|   "Like MAPHASH, but calls FUNCTION with each key in the hash table TABLE."
 | |
|   (maphash (lambda (k v)
 | |
|              (declare (ignore v))
 | |
|              (funcall function k))
 | |
|            table))
 | |
| 
 | |
| (declaim (inline maphash-values))
 | |
| (defun maphash-values (function table)
 | |
|   "Like MAPHASH, but calls FUNCTION with each value in the hash table TABLE."
 | |
|   (maphash (lambda (k v)
 | |
|              (declare (ignore k))
 | |
|              (funcall function v))
 | |
|            table))
 | |
| 
 | |
| (defun hash-table-keys (table)
 | |
|   "Returns a list containing the keys of hash table TABLE."
 | |
|   (let ((keys nil))
 | |
|     (maphash-keys (lambda (k)
 | |
|                     (push k keys))
 | |
|                   table)
 | |
|     keys))
 | |
| 
 | |
| (defun hash-table-values (table)
 | |
|   "Returns a list containing the values of hash table TABLE."
 | |
|   (let ((values nil))
 | |
|     (maphash-values (lambda (v)
 | |
|                       (push v values))
 | |
|                     table)
 | |
|     values))
 | |
| 
 | |
| (defun hash-table-alist (table)
 | |
|   "Returns an association list containing the keys and values of hash table
 | |
| TABLE."
 | |
|   (let ((alist nil))
 | |
|     (maphash (lambda (k v)
 | |
|                (push (cons k v) alist))
 | |
|              table)
 | |
|     alist))
 | |
| 
 | |
| (defun hash-table-plist (table)
 | |
|   "Returns a property list containing the keys and values of hash table
 | |
| TABLE."
 | |
|   (let ((plist nil))
 | |
|     (maphash (lambda (k v)
 | |
|                (setf plist (list* k v plist)))
 | |
|              table)
 | |
|     plist))
 | |
| 
 | |
| (defun alist-hash-table (alist &rest hash-table-initargs)
 | |
|   "Returns a hash table containing the keys and values of the association list
 | |
| ALIST. Hash table is initialized using the HASH-TABLE-INITARGS."
 | |
|   (let ((table (apply #'make-hash-table hash-table-initargs)))
 | |
|     (dolist (cons alist)
 | |
|       (ensure-gethash (car cons) table (cdr cons)))
 | |
|     table))
 | |
| 
 | |
| (defun plist-hash-table (plist &rest hash-table-initargs)
 | |
|   "Returns a hash table containing the keys and values of the property list
 | |
| PLIST. Hash table is initialized using the HASH-TABLE-INITARGS."
 | |
|   (let ((table (apply #'make-hash-table hash-table-initargs)))
 | |
|     (do ((tail plist (cddr tail)))
 | |
|         ((not tail))
 | |
|       (ensure-gethash (car tail) table (cadr tail)))
 | |
|     table))
 |