diff --git a/lib/default.nix b/lib/default.nix index 661f76bed0ef..af9716cb165f 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -295,6 +295,7 @@ let elemAt isList concatAttrValues + replaceElemAt ; inherit (self.strings) concatStrings diff --git a/lib/lists.nix b/lib/lists.nix index 1463ff622b7f..41eba34f93c5 100644 --- a/lib/lists.nix +++ b/lib/lists.nix @@ -2019,4 +2019,41 @@ rec { ::: */ concatAttrValues = set: concatLists (attrValues set); + + /** + Replaces a list's nth element with a new element + + # Inputs + + `list` + : Input list + + `idx` + : index to replace + + `newElem` + : new element to replace with + + # Type + + ``` + replaceElemAt :: [a] -> int - b -> [a] + ``` + + # Examples + :::{.example} + ## `replaceElemAt` usage example + + ```nix + lib.replaceElemAt` [1 2 3] 0 "a" + => ["a" 2 3] + ``` + + ::: + */ + replaceElemAt = + list: idx: newElem: + assert lib.assertMsg (idx >= 0 && idx < length list) + "'lists.replaceElemAt' called with index ${toString idx} on a list of size ${toString (length list)}"; + genList (i: if i == idx then newElem else elemAt list i) (length list); } diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 6c1a8c54a547..0a5c2ace0832 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -4909,4 +4909,17 @@ runTests { targetTarget = "prefix-tt"; }; }; + + testReplaceElemAt = { + expr = lib.replaceElemAt [ 1 2 3 ] 1 "a"; + expected = [ + 1 + "a" + 3 + ]; + }; + + testReplaceElemAtOutOfRange = testingThrow (lib.replaceElemAt [ 1 2 3 ] 5 "a"); + + testReplaceElemAtNegative = testingThrow (lib.replaceElemAt [ 1 2 3 ] (-1) "a"); }