about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authoradisbladis <adisbladis@gmail.com>2023-11-27 01:42:32 +1300
committeradisbladis <adisbladis@gmail.com>2023-11-27 11:37:57 +1300
commit544a1d375b47de09d6610c2059588032a9d8c192 (patch)
treedd339d12766237fedc328042a0b8a4a2164d8841 /lib
parent7e07b3ecd55ac85675c26d9b09fab9996c410681 (diff)
lib.attrsets.attrByPath: Don't allocate one extra list per lookup recursion
Using `tail` in a recursive loop like this needlessly allocates.
This changes the loop to look up by list index instead.
Diffstat (limited to 'lib')
-rw-r--r--lib/attrsets.nix32
1 files changed, 21 insertions, 11 deletions
diff --git a/lib/attrsets.nix b/lib/attrsets.nix
index 107570627c66a..52bc131ef40f2 100644
--- a/lib/attrsets.nix
+++ b/lib/attrsets.nix
@@ -34,12 +34,20 @@ rec {
     default:
     # The nested attribute set to select values from
     set:
-    let attr = head attrPath;
+    let
+      lenAttrPath = length attrPath;
+      attrByPath' = n: s: (
+        if n == lenAttrPath then s
+        else (
+          let
+            attr = elemAt attrPath n;
+          in
+          if s ? ${attr} then attrByPath' (n + 1) s.${attr}
+          else default
+        )
+      );
     in
-      if attrPath == [] then set
-      else if set ? ${attr}
-      then attrByPath (tail attrPath) default set.${attr}
-      else default;
+      attrByPath' 0 set;
 
   /* Return if an attribute from nested attribute set exists.
 
@@ -60,12 +68,14 @@ rec {
     e:
     let
       lenAttrPath = length attrPath;
-      hasAttrByPath' = n: s: let
-        attr = elemAt attrPath n;
-      in (
-        if n == lenAttrPath then true
-        else if s ? ${attr} then hasAttrByPath' (n + 1) s.${attr}
-        else false
+      hasAttrByPath' = n: s: (
+        n == lenAttrPath || (
+          let
+            attr = elemAt attrPath n;
+          in
+          if s ? ${attr} then hasAttrByPath' (n + 1) s.${attr}
+          else false
+        )
       );
     in
       hasAttrByPath' 0 e;