diff --git a/doc/manual/expressions/builtins.xml b/doc/manual/expressions/builtins.xml
index 099f90e78..446157056 100644
--- a/doc/manual/expressions/builtins.xml
+++ b/doc/manual/expressions/builtins.xml
@@ -364,6 +364,24 @@ builtins.fromJSON ''{"x": [1, 2, 3], "y": null}''
+ builtins.genList
+ generator length
+
+ Generate list of size
+ length, with each element
+ i> equal to the value returned by
+ generator i. For
+ example,
+
+
+builtins.genList (x: x * x) 5
+
+
+ returns the list [ 0 1 4 9 16 ].
+
+
+
+
builtins.getAttr
s set
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index ece76975d..5da2f3463 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1364,6 +1364,25 @@ static void prim_all(EvalState & state, const Pos & pos, Value * * args, Value &
}
+/* Apply a function to every element of a list. */
+static void prim_genList(EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+ state.forceFunction(*args[0], pos);
+ auto len = state.forceInt(*args[1], pos);
+
+ if (len < 0)
+ throw EvalError(format("cannot create list of size %1%, at %2%") % len % pos);
+
+ state.mkList(v, len);
+
+ for (unsigned int n = 0; n < len; ++n) {
+ Value * arg = state.allocValue();
+ mkInt(*arg, n);
+ mkApp(*(v.listElems()[n] = state.allocValue()), *args[0], *arg);
+ }
+}
+
+
/*************************************************************
* Integer arithmetic
*************************************************************/
@@ -1759,6 +1778,7 @@ void EvalState::createBaseEnv()
addPrimOp("__foldl'", 3, prim_foldlStrict);
addPrimOp("__any", 2, prim_any);
addPrimOp("__all", 2, prim_all);
+ addPrimOp("__genList", 2, prim_genList);
// Integer arithmetic
addPrimOp("__add", 2, prim_add);
diff --git a/tests/lang/lib.nix b/tests/lang/lib.nix
index 262cdd7e8..028a53831 100644
--- a/tests/lang/lib.nix
+++ b/tests/lang/lib.nix
@@ -54,8 +54,8 @@ rec {
const = x: y: x;
range = first: last:
- if builtins.lessThan last first
- then []
- else [first] ++ range (builtins.add first 1) last;
+ if first > last
+ then []
+ else genList (n: first + n) (last - first + 1);
}