Add foldl' primop

This commit is contained in:
Eelco Dolstra 2015-07-23 17:03:02 +02:00
parent 887bb5fa5a
commit 61af14a921
3 changed files with 38 additions and 1 deletions

View file

@ -313,6 +313,19 @@ stdenv.mkDerivation {
</varlistentry> </varlistentry>
<varlistentry><term><function>builtins.foldl</function>
<replaceable>op</replaceable> <replaceable>nul</replaceable> <replaceable>list</replaceable></term>
<listitem><para>Reduce a list by applying a binary operator, from
left to right, e.g. <literal>foldl op nul [x0 x1 x2 ...] = op (op
(op nul x0) x1) x2) ...</literal>. The operator is applied
strictly, i.e., its arguments are evaluated first. For example,
<literal>foldl (x: y: x + y) 0 [1 2 3]</literal> evaluates to
6.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.fromJSON</function> <replaceable>e</replaceable></term> <varlistentry><term><function>builtins.fromJSON</function> <replaceable>e</replaceable></term>
<listitem><para>Convert a JSON string to a Nix <listitem><para>Convert a JSON string to a Nix

View file

@ -1304,6 +1304,29 @@ static void prim_length(EvalState & state, const Pos & pos, Value * * args, Valu
} }
/* Reduce a list by applying a binary operator, from left to
right. The operator is applied strictly. */
static void prim_foldlStrict(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceFunction(*args[0], pos);
state.forceList(*args[2], pos);
Value * vCur = args[1];
if (args[2]->list.length)
for (unsigned int n = 0; n < args[2]->list.length; ++n) {
Value vTmp;
state.callFunction(*args[0], *vCur, vTmp, pos);
vCur = n == args[2]->list.length - 1 ? &v : state.allocValue();
state.callFunction(vTmp, *args[2]->list.elems[n], *vCur, pos);
}
else
v = *vCur;
state.forceValue(v);
}
/************************************************************* /*************************************************************
* Integer arithmetic * Integer arithmetic
*************************************************************/ *************************************************************/
@ -1641,6 +1664,7 @@ void EvalState::createBaseEnv()
addPrimOp("__elem", 2, prim_elem); addPrimOp("__elem", 2, prim_elem);
addPrimOp("__concatLists", 1, prim_concatLists); addPrimOp("__concatLists", 1, prim_concatLists);
addPrimOp("__length", 1, prim_length); addPrimOp("__length", 1, prim_length);
addPrimOp("__foldl'", 3, prim_foldlStrict);
// Integer arithmetic // Integer arithmetic
addPrimOp("__add", 2, prim_add); addPrimOp("__add", 2, prim_add);

View file

@ -17,7 +17,7 @@ rec {
then fold (x: y: (flatten x) ++ y) [] x then fold (x: y: (flatten x) ++ y) [] x
else [x]; else [x];
sum = fold (x: y: add x y) 0; sum = foldl' (x: y: add x y) 0;
hasSuffix = ext: fileName: hasSuffix = ext: fileName:
let lenFileName = stringLength fileName; let lenFileName = stringLength fileName;