@@ -3505,6 +3505,50 @@ static RegisterPrimOp primop_mapAttrs({
35053505 .fun = prim_mapAttrs,
35063506});
35073507
3508+ static void prim_filterAttrs (EvalState & state, const PosIdx pos, Value ** args, Value & v)
3509+ {
3510+ state.forceAttrs (*args[1 ], pos, " while evaluating the second argument passed to builtins.filterAttrs" );
3511+
3512+ if (args[1 ]->attrs ()->empty ()) {
3513+ v = *args[1 ];
3514+ return ;
3515+ }
3516+
3517+ state.forceFunction (*args[0 ], pos, " while evaluating the first argument passed to builtins.filterAttrs" );
3518+
3519+ auto attrs = state.buildBindings (args[1 ]->attrs ()->size ());
3520+
3521+ for (auto & i : *args[1 ]->attrs ()) {
3522+ Value * vName = Value::toPtr (state.symbols [i.name ]);
3523+ Value * vFun2 = state.allocValue ();
3524+ vFun2->mkApp (args[0 ], vName);
3525+ Value res;
3526+ state.callFunction (*vFun2, *i.value , res, noPos);
3527+ if (state.forceBool (
3528+ res, pos, " while evaluating the return value of the filtering function passed to builtins.filterAttrs" ))
3529+ attrs.insert (i.name , i.value );
3530+ }
3531+
3532+ v.mkAttrs (attrs.alreadySorted ());
3533+ }
3534+
3535+ static RegisterPrimOp primop_filterAttrs ({
3536+ .name = " __filterAttrs" ,
3537+ .args = {" f" , " attrset" },
3538+ .doc = R"(
3539+ Return an attribute set consisting of the attributes in *attrset* for which
3540+ the function *f* returns `true`. The function *f* is called with two arguments:
3541+ the name of the attribute and the value of the attribute. For example,
3542+
3543+ ```nix
3544+ builtins.filterAttrs (name: value: name == "foo") { foo = 1; bar = 2; }
3545+ ```
3546+
3547+ evaluates to `{ foo = 1; }`.
3548+ )" ,
3549+ .fun = prim_filterAttrs,
3550+ });
3551+
35083552static void prim_zipAttrsWith (EvalState & state, const PosIdx pos, Value ** args, Value & v)
35093553{
35103554 // we will first count how many values are present for each given key.
0 commit comments