Skip to content

lib.attrsets.foldAttrs': init #427473

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

Conversation

YorikSar
Copy link
Contributor

Same as foldAttrs, but passing attribute name to the function.
This is helpful in cases when the function needs to log or throw errors with attribute names included in the message. For example:

assertUniqueAttrs = foldAttrs' (
  name: v: acc:
  assert (assertMsg (acc == null) "${name} is defined in multiple sets");
  v
) null

Things done


Add a 👍 reaction to pull requests you find important.

@nix-owners nix-owners bot requested review from hsjobeki and infinisil July 22, 2025 15:13
@nixpkgs-ci nixpkgs-ci bot added 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 6.topic: lib The Nixpkgs function library labels Jul 22, 2025
Same as `foldAttrs`, but passing attribute name to the function.
This is helpful in cases when the function needs to log or throw errors
with attribute names included in the message. For example:

```
assertUniqueAttrs = foldAttrs' (
  name: v: acc:
  assert (assertMsg (acc == null) "${name} is defined in multiple sets");
  v
) null
```
Copy link
Contributor

@hsjobeki hsjobeki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the functionality can already be achieved with zipAttrsWith. If you just want one accumulator per attribute name.
You can use zipAttrsWith and do one fold operation with an accumulator like this

builtins.zipAttrsWith (name: values: foldl' (acc: v: ..) null values)  [ { a = 1; } { a = 2; } ] 

For your assertUniqueAttrs you could even skip the inner fold and directly throw (or assert) the error

builtins.zipAttrsWith (name: values: if builtins.length values > 1 then throw "this" else lib.head values)  [ { a = 1; } { a = 2; } ]

I'd open considering this if more convincing use-cases would be presented but as is this function doesn't really introduce a newer or cleaner way to do zipping and folding

## `lib.attrsets.foldAttrs'` usage example

```nix
foldAttrs' (name: item: acc: ["${name}${toString item}"] ++ acc) [] [{ a = 2; b = 3; } { a = 4; }]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example is equivalent to the existing

    zipAttrsWith (name: values: map (v: name + toString v) values) [{ a = 2; b = 3; } { a = 4; }]

Only missing feature would be the accumulator. But the mentioned use-cases didn't really convince the need for that.

@YorikSar
Copy link
Contributor Author

@hsjobeki Thanks for the suggestion, we'll try running with it for now. We'll see if any use cases that would require foldAttrs with names pop up.

@YorikSar YorikSar closed this Aug 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: lib The Nixpkgs function library 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants