I’m probably missing something from the 13th Nix Pill, but when they show
callPackage = path: overrides: let f = import path; in f ((builtins.intersectAttrs (builtins.functionArgs f) allPkgs) // overrides);
I don’t understand why it’s not just something like
import path (allPkgs // overrides) where the package is required to have variadic arguments?
The way the callPackage pattern is explained it seems like it’s important to first restrict the set of all packages to the ones the function is accepting, but Nix is a lazy language. Wouldn’t passing the whole
nixpkgs be the same as passing
builtins.intersectAttrs (builtins.functionArgs f) nixpkgs
or possibly even more efficient, because there is no need to evaluate the intersection (even though lazily), and only the needed part of
nixpkgs is accepted by the called function?
On one way I can see how passing in “everything by default” would be considered bad practice, but we’re really doing that anyway, just restricting the “everything” on the side of the caller and not on the side of the callee, even though both are transparent to the user.