Add procedures to convert alists into hash tables.
authorDavid Thompson <dthompson2@worcester.edu>
Sun, 20 Oct 2013 02:43:37 +0000 (22:43 -0400)
committerMark H Weaver <mhw@netris.org>
Tue, 19 Nov 2013 04:03:38 +0000 (23:03 -0500)
* module/ice-9/hash-table.scm: New module.

* test-suite/tests/hash.test ("alist conversion"): Add tests.

* doc/ref/api-compound.texi (Hash Table Reference): Add docs.

doc/ref/api-compound.texi
module/Makefile.am
module/ice-9/hash-table.scm [new file with mode: 0644]
test-suite/tests/hash.test

index 94e0145..0b14c48 100644 (file)
@@ -3829,6 +3829,27 @@ then it can use @var{size} to avoid rehashing when initial entries are
 added.
 @end deffn
 
+@deffn {Scheme Procedure} alist->hash-table alist
+@deffnx {Scheme Procedure} alist->hashq-table alist
+@deffnx {Scheme Procedure} alist->hashv-table alist
+@deffnx {Scheme Procedure} alist->hashx-table hash assoc alist
+Convert @var{alist} into a hash table. When keys are repeated in
+@var{alist}, the leftmost association takes precedence.
+
+@example
+(use-modules (ice-9 hash-table))
+(alist->hash-table '((foo . 1) (bar . 2)))
+@end example
+
+When converting to an extended hash table, custom @var{hash} and
+@var{assoc} procedures must be provided.
+
+@example
+(alist->hashx-table hash assoc '((foo . 1) (bar . 2)))
+@end example
+
+@end deffn
+
 @deffn {Scheme Procedure} hash-table? obj
 @deffnx {C Function} scm_hash_table_p (obj)
 Return @code{#t} if @var{obj} is a abstract hash table object.
index e8dcd4a..8a7befd 100644 (file)
@@ -207,6 +207,7 @@ ICE_9_SOURCES = \
   ice-9/format.scm \
   ice-9/futures.scm \
   ice-9/getopt-long.scm \
+  ice-9/hash-table.scm \
   ice-9/hcons.scm \
   ice-9/i18n.scm \
   ice-9/iconv.scm \
diff --git a/module/ice-9/hash-table.scm b/module/ice-9/hash-table.scm
new file mode 100644 (file)
index 0000000..ca9d2fd
--- /dev/null
@@ -0,0 +1,45 @@
+;;;; hash-table.scm --- Additional hash table procedures
+;;;; Copyright (C) 2013 Free Software Foundation, Inc.
+;;;;
+;;;; This library is free software; you can redistribute it and/or
+;;;; modify it under the terms of the GNU Lesser General Public
+;;;; License as published by the Free Software Foundation; either
+;;;; version 3 of the License, or (at your option) any later version.
+;;;;
+;;;; This library is distributed in the hope that it will be useful,
+;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;;; Lesser General Public License for more details.
+;;;;
+;;;; You should have received a copy of the GNU Lesser General Public
+;;;; License along with this library; if not, write to the Free Software
+;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;;;;
+
+(define-module (ice-9 hash-table)
+  #:export (alist->hash-table
+            alist->hashq-table
+            alist->hashv-table
+            alist->hashx-table))
+
+(define-syntax-rule (define-alist-converter name hash-set-proc)
+  (define (name alist)
+    "Convert ALIST into a hash table."
+    (let ((table (make-hash-table)))
+      (for-each (lambda (pair)
+                  (hash-set-proc table (car pair) (cdr pair)))
+                (reverse alist))
+      table)))
+
+(define-alist-converter alist->hash-table hash-set!)
+(define-alist-converter alist->hashq-table hashq-set!)
+(define-alist-converter alist->hashv-table hashv-set!)
+
+(define (alist->hashx-table hash assoc alist)
+  "Convert ALIST into a hash table with custom HASH and ASSOC
+procedures."
+  (let ((table (make-hash-table)))
+    (for-each (lambda (pair)
+                (hashx-set! hash assoc table (car pair) (cdr pair)))
+              (reverse alist))
+    table))
index 3bd4004..ad247f5 100644 (file)
@@ -18,7 +18,8 @@
 
 (define-module (test-suite test-numbers)
   #:use-module (test-suite lib)
-  #:use-module (ice-9 documentation))
+  #:use-module (ice-9 documentation)
+  #:use-module (ice-9 hash-table))
 
 ;;;
 ;;; hash
                             (lambda ()
                               (write (make-hash-table 100)))))))
 
+;;;
+;;; alist->hash-table
+;;;
+
+(with-test-prefix
+  "alist conversion"
+
+  (pass-if "alist->hash-table"
+    (let ((table (alist->hash-table '(("foo" . 1)
+                                      ("bar" . 2)
+                                      ("foo" . 3)))))
+      (and (= (hash-ref table "foo") 1)
+           (= (hash-ref table "bar") 2))))
+
+  (pass-if "alist->hashq-table"
+    (let ((table (alist->hashq-table '((foo . 1)
+                                       (bar . 2)
+                                       (foo . 3)))))
+      (and (= (hashq-ref table 'foo) 1)
+           (= (hashq-ref table 'bar) 2))))
+
+  (pass-if "alist->hashv-table"
+    (let ((table (alist->hashv-table '((1 . 1)
+                                       (2 . 2)
+                                       (1 . 3)))))
+      (and (= (hashv-ref table 1) 1)
+           (= (hashv-ref table 2) 2))))
+
+  (pass-if "alist->hashx-table"
+    (let ((table (alist->hashx-table hash assoc '((foo . 1)
+                                                  (bar . 2)
+                                                  (foo . 3)))))
+      (and (= (hashx-ref hash assoc table 'foo) 1)
+           (= (hashx-ref hash assoc table 'bar) 2)))))
+
 ;;;
 ;;; usual set and reference
 ;;;