Skip to content

Commit a627178

Browse files
not-ronjingerjonringer
authored andcommitted
Add filterAttrs builtin
1 parent 52ea293 commit a627178

File tree

5 files changed

+56
-0
lines changed

5 files changed

+56
-0
lines changed

src/libexpr/primops.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3505,6 +3505,49 @@ 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 * callArgs[] = {vName, i.value};
3524+
Value res;
3525+
state.callFunction(*args[0], callArgs, res, noPos);
3526+
if (state.forceBool(
3527+
res, pos, "while evaluating the return value of the filtering function passed to builtins.filterAttrs"))
3528+
attrs.insert(i.name, i.value);
3529+
}
3530+
3531+
v.mkAttrs(attrs.alreadySorted());
3532+
}
3533+
3534+
static RegisterPrimOp primop_filterAttrs({
3535+
.name = "__filterAttrs",
3536+
.args = {"f", "attrset"},
3537+
.doc = R"(
3538+
Return an attribute set consisting of the attributes in *attrset* for which
3539+
the function *f* returns `true`. The function *f* is called with two arguments:
3540+
the name of the attribute and the value of the attribute. For example,
3541+
3542+
```nix
3543+
builtins.filterAttrs (name: value: name == "foo") { foo = 1; bar = 2; }
3544+
```
3545+
3546+
evaluates to `{ foo = 1; }`.
3547+
)",
3548+
.fun = prim_filterAttrs,
3549+
});
3550+
35083551
static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value ** args, Value & v)
35093552
{
35103553
// we will first count how many values are present for each given key.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ a = 3; }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
builtins.filterAttrs (name: value: name == "a") {
2+
a = 3;
3+
b = 6;
4+
c = 10;
5+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ b = 6; c = 10; }
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
builtins.filterAttrs (name: value: value > 5) {
3+
a = 3;
4+
b = 6;
5+
c = 10;
6+
}

0 commit comments

Comments
 (0)