2017-09-06 1 views
6

Pour appeler une fonction Nix qui utilise ensemble destructuration, vous devez passer un ensemble avec exactement les clés dont il a besoin, ni plus ni moins:Comment les fonctions d'appel de "callPackage" de Nix sont-elles définies sans ellipses?

nix-repl> ({ a }: a) { a = 4; b = 5; } 
error: anonymous function at (string):1:2 called with unexpected argument ‘b’, at (string):1:1 

L'exception à cette règle est si l'argument de la fonction liste contient des points de suspension à la fin:

nix-repl> ({ a, ... }: a) { a = 4; b = 5; } 
4 

Cependant, la plupart des paquets de nixpkgs sont constitués d'un fichier default.nix contenant une fonction qui est définie pas avec cette ellipse. Pourtant, quand vous utilisez callPackage, il parvient à appeler ces fonctions et à leur transmettre uniquement les arguments dont il a besoin. Comment cela est-il mis en œuvre?

Répondre

5

Il y a un primop de réflexion, qui peut déconstruire l'argument de la fonction:

nix-repl> __functionArgs ({ x ? 1, y }: x) 
{ x = true; y = false; } 

callPackage puis itère sur les noms d'attribut, récupère les paquets requis et constucts le attrset des paquets, qui est alimenté par la suite à la fonction appelée.

Voici un exemple simple:

nix-repl> callWithExtraArgs = f: args: 
      let 
       args' = __intersectAttrs (__functionArgs f) args; 
      in 
       f args' 

nix-repl> callWithExtraArgs ({ x }: x + 1) { x = 4; y = 7; } 
5