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.
This commit is contained in:
adisbladis 2023-11-27 01:42:32 +13:00
parent 7e07b3ecd5
commit 544a1d375b

View file

@ -34,12 +34,20 @@ rec {
default: default:
# The nested attribute set to select values from # The nested attribute set to select values from
set: 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 in
if attrPath == [] then set attrByPath' 0 set;
else if set ? ${attr}
then attrByPath (tail attrPath) default set.${attr}
else default;
/* Return if an attribute from nested attribute set exists. /* Return if an attribute from nested attribute set exists.
@ -60,12 +68,14 @@ rec {
e: e:
let let
lenAttrPath = length attrPath; lenAttrPath = length attrPath;
hasAttrByPath' = n: s: let hasAttrByPath' = n: s: (
attr = elemAt attrPath n; n == lenAttrPath || (
in ( let
if n == lenAttrPath then true attr = elemAt attrPath n;
else if s ? ${attr} then hasAttrByPath' (n + 1) s.${attr} in
else false if s ? ${attr} then hasAttrByPath' (n + 1) s.${attr}
else false
)
); );
in in
hasAttrByPath' 0 e; hasAttrByPath' 0 e;