about summary refs log tree commit diff
path: root/users/sterni/nix/list/default.nix
diff options
context:
space:
mode:
authorsterni <sternenseemann@systemli.org>2024-03-09T12·17+0100
committerclbot <clbot@tvl.fyi>2024-03-10T18·05+0000
commitad9b08e43dd06260a52543f9078fc921c130cc9a (patch)
tree4d4c1a3fb5e2e7b1761b7c8ef12d5bb67f8501ba /users/sterni/nix/list/default.nix
parent37703c9e44208c1929e186dc45d3d03984826398 (diff)
feat(sterni/nix/lists): implement transpose r/7663
This function is inspired by BQN's [⍉] though it is much less elegant
since Nix lacks multi-dimensional arrays. I thought this would be useful
to to avoid multiple `map`s over a single list if we want to return
multiple, separate values from it:

  transpose (builtins.map (x: [ (calcA x) (calcB x) ]) myList)

  # => [ [ (calcA a) … ] [ (calcB a) … ] ]

While this is quite elegant, it turns out that it is faster to write out
multiple maps:

  [ (builtins.map calcA myList) (builtins.map calcB myList) ]

[⍉]: https://mlochbaum.github.io/BQN/doc/transpose.html

Change-Id: Ic333c33af38ab03573b215c9696d75caf2ee18e7
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11113
Reviewed-by: sterni <sternenseemann@systemli.org>
Autosubmit: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
Diffstat (limited to 'users/sterni/nix/list/default.nix')
-rw-r--r--users/sterni/nix/list/default.nix30
1 files changed, 30 insertions, 0 deletions
diff --git a/users/sterni/nix/list/default.nix b/users/sterni/nix/list/default.nix
new file mode 100644
index 000000000000..568a76d637a1
--- /dev/null
+++ b/users/sterni/nix/list/default.nix
@@ -0,0 +1,30 @@
+{ ... }:
+
+{
+  /* For a list of length n that consists of lists of length m,
+     return a list of length m containing lists of length n
+     so that
+
+         builtins.elemAt (builtins.elemAt orig a) b
+         == builtins.elemAt (builtins.elemAt transposed b) a
+
+     Essentially, if you think of the nested list as an array with two
+     dimensions, the two index axes are swapped.
+
+     The length of the inner lists m is determined based on the first element
+     and assumed to be used for all other lists. Malformed input data may
+     cause the function to crash or lose data.
+
+     Type: <n>[ <m>[ ] ] -> <m>[ <n>[ ] ]
+  */
+  transpose = list:
+    let
+      innerLength = builtins.length (builtins.head list);
+      outerLength = builtins.length list;
+    in
+    builtins.genList
+      (inner: builtins.genList
+        (outer: builtins.elemAt (builtins.elemAt list outer) inner)
+        outerLength)
+      innerLength;
+}