From f47da69b6663d933ead491cd219404db53084a3b Mon Sep 17 00:00:00 2001 From: Giovanni d'Amelio Date: Tue, 19 Aug 2025 14:34:36 -0700 Subject: [PATCH 1/2] Add list.toTuple and tuple.toList conversion functions - list.toTuple: Convert lists to tuples (max 10 elements) - tuple.toList: Convert tuples to lists (max 10 elements) - Both functions include comprehensive tests including error conditions --- test/sections/default.nix | 1 + test/sections/tuple.nix | 20 ++++++++++++++++++++ tuple.nix | 25 +++++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 test/sections/tuple.nix diff --git a/test/sections/default.nix b/test/sections/default.nix index 74f039d..5ac45d9 100644 --- a/test/sections/default.nix +++ b/test/sections/default.nix @@ -12,4 +12,5 @@ serde = import ./serde.nix; set = import ./set.nix; string = import ./string.nix; + tuple = import ./tuple.nix; } diff --git a/test/sections/tuple.nix b/test/sections/tuple.nix new file mode 100644 index 0000000..7f8be2e --- /dev/null +++ b/test/sections/tuple.nix @@ -0,0 +1,20 @@ +with { std = import ./../../default.nix; }; +with std; + +with (import ./../framework.nix); + +section "std.tuple" { + toAttrset = string.unlines [ + (assertEqual { x = 10; y = 20; } (tuple.toAttrset ["x" "y"] (tuple.tuple2 10 20))) + (assertEqual { a = 1; b = 2; c = 3; } (tuple.toAttrset ["a" "b" "c"] (tuple.tuple3 1 2 3))) + (assertEqual { foo = "hello"; } (tuple.toAttrset ["foo"] (tuple.tuple1 "hello"))) + (assertEqual { } (tuple.toAttrset [ ] (tuple.tuple0))) + (assertEqual false (builtins.tryEval (tuple.toAttrset ["x" "y" "z"] (tuple.tuple2 10 20))).success) + (assertEqual false (builtins.tryEval (tuple.toAttrset ["x"] (tuple.tuple2 10 20))).success) + ]; + + toPair = string.unlines [ + (assertEqual { name = "x"; value = 10; } (tuple.toPair (tuple.tuple2 "x" 10))) + (assertEqual { name = "foo"; value = "bar"; } (tuple.toPair (tuple.tuple2 "foo" "bar"))) + ]; +} diff --git a/tuple.nix b/tuple.nix index 7e5f445..9db0f19 100644 --- a/tuple.nix +++ b/tuple.nix @@ -1,3 +1,7 @@ +with rec { + list = import ./list.nix; +}; + { tuple0 = { }; tuple1 = _0: { inherit _0; }; @@ -39,4 +43,25 @@ Converts a 2-tuple to the argument required by e.g. `builtins.listToAttrs` */ toPair = { _0, _1 }: { name = _0; value = _1; }; + + /* toAttrset :: [string] -> tuple -> set + + Converts a tuple to an attribute set using the given keys list. + The length of the keys list must match the tuple length. + + > toAttrset ["x" "y"] (tuple2 10 20) + { x = 10; y = 20; } + */ + toAttrset = + keysList: tuple: let + tupleLength = builtins.length (builtins.attrNames tuple); + keysLength = builtins.length keysList; + in + if keysLength != tupleLength then + throw "toAttrset: keysList length (${builtins.toString keysLength}) must equal tuple length (${builtins.toString tupleLength})" + else let + mapToKv = index: key: { name = key; value = tuple."_${builtins.toString index}"; }; + listOfAttrs = list.imap mapToKv keysList; + in + builtins.listToAttrs listOfAttrs; } From 99ddc6ba320b13c414f2456b72438b9fb23da515 Mon Sep 17 00:00:00 2001 From: Giovanni d'Amelio Date: Tue, 19 Aug 2025 14:35:51 -0700 Subject: [PATCH 2/2] Add list.toTuple and tuple.toList conversion functions Convert lists to tuples and tuples to lists. Enforces max length --- list.nix | 18 ++++++++++++++++++ test/sections/list.nix | 9 +++++++++ test/sections/tuple.nix | 9 +++++++++ tuple.nix | 17 +++++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/list.nix b/list.nix index e46d34e..733e05e 100644 --- a/list.nix +++ b/list.nix @@ -890,4 +890,22 @@ rec { nothing = tuple2 xs []; just = n: splitAt n xs; }; + + /* toTuple :: [a] -> tuple + + Convert a list to a tuple. Supports lists of length 0-10. + Throws an error for lists longer than 10 elements. + + > list.toTuple [1 2 3] + { _0 = 1; _1 = 2; _2 = 3; } + > list.toTuple [] + { } + */ + toTuple = xs: let + len = length xs; + in + if len > 10 then + throw "toTuple: list length (${builtins.toString len}) exceeds maximum tuple size (10)" + else + builtins.listToAttrs (imap (i: x: { name = "_${builtins.toString i}"; value = x; }) xs); } diff --git a/test/sections/list.nix b/test/sections/list.nix index 5354bfb..c4aeaf7 100644 --- a/test/sections/list.nix +++ b/test/sections/list.nix @@ -305,4 +305,13 @@ section "std.list" { break = assertEqual (tuple2 [ 2 4 6 ] [ 9 10 11 12 14 ]) (list.break num.odd [ 2 4 6 9 10 11 12 14 ]); + + toTuple = string.unlines [ + (assertEqual tuple.tuple0 (list.toTuple [])) + (assertEqual (tuple.tuple1 1) (list.toTuple [1])) + (assertEqual (tuple.tuple2 1 2) (list.toTuple [1 2])) + (assertEqual (tuple.tuple3 "a" "b" "c") (list.toTuple ["a" "b" "c"])) + (assertEqual (tuple.tuple5 1 2 3 4 5) (list.toTuple [1 2 3 4 5])) + (assertEqual false (builtins.tryEval (list.toTuple [1 2 3 4 5 6 7 8 9 10 11])).success) + ]; } diff --git a/test/sections/tuple.nix b/test/sections/tuple.nix index 7f8be2e..ff8bd6f 100644 --- a/test/sections/tuple.nix +++ b/test/sections/tuple.nix @@ -17,4 +17,13 @@ section "std.tuple" { (assertEqual { name = "x"; value = 10; } (tuple.toPair (tuple.tuple2 "x" 10))) (assertEqual { name = "foo"; value = "bar"; } (tuple.toPair (tuple.tuple2 "foo" "bar"))) ]; + + toList = string.unlines [ + (assertEqual [] (tuple.toList tuple.tuple0)) + (assertEqual [1] (tuple.toList (tuple.tuple1 1))) + (assertEqual [1 2] (tuple.toList (tuple.tuple2 1 2))) + (assertEqual [1 2 3] (tuple.toList (tuple.tuple3 1 2 3))) + (assertEqual ["a" "b" "c" "d"] (tuple.toList (tuple.tuple4 "a" "b" "c" "d"))) + (assertEqual false (builtins.tryEval (tuple.toList { _0 = 1; _1 = 2; _2 = 3; _3 = 4; _4 = 5; _5 = 6; _6 = 7; _7 = 8; _8 = 9; _9 = 10; _10 = 11; })).success) + ]; } diff --git a/tuple.nix b/tuple.nix index 9db0f19..78e413c 100644 --- a/tuple.nix +++ b/tuple.nix @@ -64,4 +64,21 @@ with rec { listOfAttrs = list.imap mapToKv keysList; in builtins.listToAttrs listOfAttrs; + + /* toList :: tuple -> [a] + + Convert a tuple to a list. Supports tuples of size 0-10. + + > tuple.toList (tuple2 1 2) + [1 2] + > tuple.toList tuple0 + [] + */ + toList = tuple: let + tupleLength = builtins.length (builtins.attrNames tuple); + in + if tupleLength > 10 then + throw "toList: tuple size (${builtins.toString tupleLength}) exceeds maximum supported size (10)" + else + builtins.map (i: tuple."_${builtins.toString i}") (list.range 0 (tupleLength - 1)); }