-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
builtins.mergeMapAttrs
(or builtins.concatMapAttrs
)
#11887
Comments
Could you give some example how a function call would look like? Same as concatMapAttrs ? mergeMapAttrs
(name: value: { ${name + "-mapped"} = value * 2 ; } )
{ foo = 1; bar =2; nested.foo = 3; }
=>
{
{ foo-mapped = 2; bar-mapped = 4; nested-mapped.foo = 6; }
} Would it make sense to accept an optional merge function. mergeMapAttrs {
mapFn = (name: value: { ${name + "-mapped"} = value * 2 ; } );
mergeFn = (name: values: merge name values) # defaults to an error function?
}
{ foo = 1; bar =2; nested.foo = 3; }
=>
{
{ foo-mapped = 2; bar-mapped = 4; nested-mapped.foo = 6; }
} would taking an attribute set as arguments add some benefit? in this case: default behavior that can be customized. |
Yes. I've updated the description.
Perhaps, but it has a slight cost, and not much, but non-zero benefit. See the alternatives section.
In the current evaluator implementation, "argument attrsets" aren't special or optimized, whereas curried function application of positional arguments to primops is optimized. I'd like this to make no difference, but optimizing those calls is non-trivial, because we don't have static knowledge of the function, given an application |
I have to admit i am a big fan of this Idea overall. |
Team meeting notes:
|
This issue has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2024-11-20-nix-team-meeting-minutes-196/56688/1 |
Is your feature request related to a problem? Please describe.
Nixpkgs
lib
definesconcatMapAttrs f attrs
, which is a very versatile function. (To those it may concern: by virtue of being almost the monadic bind operation on attrsets. See here. Almost => no associativity due to attribute name collisions iirc)Describe the solution you'd like
Add to
builtins
a primop that behaves like Nixpkgs'lib.concatMapAttrs
. It could bebuiltins.concatMapAttrs
or a different name, such asflatMap
attrs ormergeMapAttrs
. Its implementation will be slightly more efficient than that inlib
, andlib
may reuse it, so that it becomes a polyfill.The added efficiency comes from having no intermediate Nix lists, and may build the attrset in one go.
The current implementation in
lib
has the following behaviors, which could be optimized away (in order of increasing implementation work):f
call (except the final one which is the return value)f
(1) and (2) a trivially solved by implementing this in C++.
(3) may feel unavoidable, but can be improved with Prototype: accumulate attrset updates, perform k-way merge #11290
If we pick a new name, we could make attribute name collisions an error, which iirc would make it a lawful monad in all the successful cases. Errors are better than buggy behavior somewhere deep down in some expression, because how would you find the bug.
Describe alternatives you've considered
Perhaps make it
flatMapAttrs
ormergeMapAttrs
.concat
kinda works by extrapolating from lists, but I'm not super happy about that.mergeMapAttrsWith (name: values: merge name values) f attrs
to handle the collisions.This is like
zipAttrsWith (name: values: if length values == 1 then head values else m name values)
but without allocating a whole bunch of singleton lists.Additional context
Priorities
Add 👍 to issues you find important.
The text was updated successfully, but these errors were encountered: