From cd57f867069c4e86a9c02682ddec27baa21152ac Mon Sep 17 00:00:00 2001 From: Arun Isaac Date: Wed, 31 Dec 2025 21:11:15 +0000 Subject: utils: Require arity for mapn. With an empty list, mapn cannot know the number of values proc would return. mapn therefore needs to know the arity of proc. To provide for existing callers of mapn, we add a map2 function variant. Finally, we add a test case testing mapn on an empty list. --- ccwl/ccwl.scm | 2 +- ccwl/utils.scm | 28 +++++++++++++++++++--------- tests/utils.scm | 14 ++++++++++++-- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/ccwl/ccwl.scm b/ccwl/ccwl.scm index 4480314..8f02b0c 100644 --- a/ccwl/ccwl.scm +++ b/ccwl/ccwl.scm @@ -743,7 +743,7 @@ represented by objects." (list))) ;; tee ((tee expressions ...) - (let ((key-lists step-lists (mapn (cut collect-steps <> input-keys) + (let ((key-lists step-lists (map2 (cut collect-steps <> input-keys) #'(expressions ...)))) (values ;; Global workflow input keys may be duplicated across the diff --git a/ccwl/utils.scm b/ccwl/utils.scm index 3c18efd..2abc404 100644 --- a/ccwl/utils.scm +++ b/ccwl/utils.scm @@ -1,5 +1,5 @@ ;;; ccwl --- Concise Common Workflow Language -;;; Copyright © 2021, 2022, 2023 Arun Isaac +;;; Copyright © 2021, 2022, 2023, 2025 Arun Isaac ;;; ;;; This file is part of ccwl. ;;; @@ -39,6 +39,7 @@ lambda** syntax-lambda** mapn + map2 foldn filter-mapi)) @@ -311,22 +312,31 @@ element. For example, lst (iota (length lst)))) -(define (mapn proc lst) +(define (mapn proc lst n) "Map the procedure PROC over list LST and return a list containing -the results. PROC can return multiple values, in which case, an equal -number of lists are returned. For example, +the results. PROC must return N values, in which case, N lists are +returned. For example, (mapn (lambda (n) (values (expt n 2) (expt n 3))) - (iota 5)) + (iota 5) + 2) => (0 1 4 9 16) => (0 1 8 27 64)" (apply values - (apply zip - (map (lambda (x) - (call-with-values (cut proc x) list)) - lst)))) + (match lst + ;; With an empty list, we cannot know the number of values + ;; proc would return. Hence this special case. + (() (make-list n '())) + (_ + (apply zip + (map (lambda (x) + (call-with-values (cut proc x) list)) + lst)))))) + +(define map2 + (cut mapn <> <> 2)) (define (foldn proc lst . inits) "Apply PROC to the elements of LST to build a result, and return diff --git a/tests/utils.scm b/tests/utils.scm index 50c3396..d786d02 100644 --- a/tests/utils.scm +++ b/tests/utils.scm @@ -1,5 +1,5 @@ ;;; ccwl --- Concise Common Workflow Language -;;; Copyright © 2021, 2022, 2023 Arun Isaac +;;; Copyright © 2021, 2022, 2023, 2025 Arun Isaac ;;; ;;; This file is part of ccwl. ;;; @@ -194,7 +194,17 @@ (let ((squares cubes (mapn (lambda (n) (values (expt n 2) (expt n 3))) - (iota 5)))) + (iota 5) + 2))) + (list squares cubes))) + +(test-equal "mapn on an empty list" + '(() ()) + (let ((squares cubes (mapn (lambda (n) + (values (expt n 2) + (expt n 3))) + '() + 2))) (list squares cubes))) (test-equal "foldn" -- cgit 1.4.1