summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--guix/records.scm16
-rw-r--r--tests/records.scm6
2 files changed, 19 insertions, 3 deletions
diff --git a/guix/records.scm b/guix/records.scm
index 57664df5a6..8dc733b8ff 100644
--- a/guix/records.scm
+++ b/guix/records.scm
@@ -198,9 +198,19 @@ thunked fields."
                                                          #'((field options ...)
                                                             ...))))))))))
 
-(define (alist->record alist make keys)
-  "Apply MAKE to the values associated with KEYS in ALIST."
-  (let ((args (map (cut assoc-ref alist <>) keys)))
+(define* (alist->record alist make keys
+                        #:optional (multiple-value-keys '()))
+  "Apply MAKE to the values associated with KEYS in ALIST.  Items in KEYS that
+are also in MULTIPLE-VALUE-KEYS are considered to occur possibly multiple
+times in ALIST, and thus their value is a list."
+  (let ((args (map (lambda (key)
+                     (if (member key multiple-value-keys)
+                         (filter-map (match-lambda
+                                      ((k . v)
+                                       (and (equal? k key) v)))
+                                     alist)
+                         (assoc-ref alist key)))
+                   keys)))
     (apply make args)))
 
 (define (object->fields object fields port)
diff --git a/tests/records.scm b/tests/records.scm
index d0635ebb1f..712eb83a09 100644
--- a/tests/records.scm
+++ b/tests/records.scm
@@ -158,6 +158,12 @@ Version: 1.5
     (list (recutils->alist p)
           (recutils->alist p))))
 
+(test-equal "alist->record" '((1 2) b c)
+  (alist->record '(("a" . 1) ("b" . b) ("c" . c) ("a" . 2))
+                 list
+                 '("a" "b" "c")
+                 '("a")))
+
 (test-end)