Sorry if this is the wrong category but I’m posting this as a discussion rather than help. I’m just interested in peoples opinions.
I have seen multiple different implementations of forAllSystems used in flakes meant to run on different OSs/Architectures. Here are a few:
forAllSystems = f:
builtins.listToAttrs (map (system: {
name = system;
value = f system;
})
systems);
# or
forAllSystems = nixpkgs.lib.genAttrs systems;
There is, of course, the flake-utils implementation:
eachSystem = eachSystemOp (
# Merge outputs for each system.
f: attrs: system:
let
ret = f system;
in
builtins.foldl' (
attrs: key:
attrs
// {
${key} = (attrs.${key} or { }) // {
${system} = ret.${key};
};
}
) attrs (builtins.attrNames ret)
);
because it’s short and basic and doesn’t need another input just for this and was what was in the template I copied initially and has just stayed there since without having ever been thought about again until now
Fair, thank you for thinking about it now! I’ve been trying to wrap my head around how this differs from forAllSystems = nixpkgs.lib.genAttrs supportedSystems; and I think it is an eta-reduction of your code.
A much simplified case in nix would be:
nix-repl> concatA = x: x + "A"
nix-repl> concatA2 = (f: concatA) (g: f g)
nix-repl> concatA "B"
"BA"
nix-repl> concatA2 "B"
"BA"
Or slightly closer to the code
nix-repl> forAll = inputs.nixpkgs.lib.genAttrs ["a" "b"]
nix-repl> forAll (x: x)
{
a = "a";
b = "b";
}
nix-repl> forAll2 = f: forAll (s: f s)
nix-repl> forAll2 (x: x)
{
a = "a";
b = "b";
}
I’m new to functional programming so this is fascinating.
In a flake that doesn’t rely on nixpkgs, this is surely the best option. Adding in nixpkgs for this would be a +50 MB dependency.
flake-utils is just bad in terms of not-stopping people from adding in system where it shouldn’t be added, a common footgun. IMO that repo should be archived considering they already made a better replacement (blueprint).
Interesting. I didn’t know about blueprint and hadn’t considered the dependency on Nixpkgs. Is there a way to import just nixpkgs built in’s without the whole 50mb?
Thank you! Yeah, probably not worth to import just for that but nonetheless can help with inspiration writing nix.
In the meantime I found another version using builtins.getAttr
forAllSystems = f:
nixpkgs.lib.genAttrs systems (
system:
f (builtins.getAttr system nixpkgs.legacyPackages)
);
Or without nixpkgs dependency in the generation
forAllSystems = f:
builtins.listToAttrs (map (system: {
name = system;
value = f (builtins.getAttr system nixpkgs.legacyPackages);
})
systems);