Nix 的 "callPackage" 如何调用没有省略号定义的函数?
How does Nix's "callPackage" call functions defined without an ellipsis?
要调用一个使用集合解构的 Nix 函数,您需要向它传递一个集合完全它需要的键,不多也不少:
nix-repl> ({ a }: a) { a = 4; b = 5; }
error: anonymous function at (string):1:2 called with unexpected argument ‘b’, at (string):1:1
如果函数的参数列表末尾包含省略号,则例外:
nix-repl> ({ a, ... }: a) { a = 4; b = 5; }
4
但是,nixpkgs 中的大多数软件包都包含一个 default.nix
文件,其中包含一个 而非 使用此省略号定义的函数。然而,不知何故,当您使用 callPackage
时,它设法调用这些函数并只向它们传递它们需要的参数。这是如何实现的?
有一个反射primop,可以解构函数参数:
nix-repl> __functionArgs ( { x ? 1, y }: x )
{ x = true; y = false; }
callPackage
然后遍历这些属性名称,获取所需的包并构造包的属性集,稍后将其提供给被调用的函数。
这是一个简单的例子:
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
要浏览 Nix primops,请转到 15.5. Built-in Functions in the Nix manual (or see the docs of the unstable branch)。
要调用一个使用集合解构的 Nix 函数,您需要向它传递一个集合完全它需要的键,不多也不少:
nix-repl> ({ a }: a) { a = 4; b = 5; }
error: anonymous function at (string):1:2 called with unexpected argument ‘b’, at (string):1:1
如果函数的参数列表末尾包含省略号,则例外:
nix-repl> ({ a, ... }: a) { a = 4; b = 5; }
4
但是,nixpkgs 中的大多数软件包都包含一个 default.nix
文件,其中包含一个 而非 使用此省略号定义的函数。然而,不知何故,当您使用 callPackage
时,它设法调用这些函数并只向它们传递它们需要的参数。这是如何实现的?
有一个反射primop,可以解构函数参数:
nix-repl> __functionArgs ( { x ? 1, y }: x )
{ x = true; y = false; }
callPackage
然后遍历这些属性名称,获取所需的包并构造包的属性集,稍后将其提供给被调用的函数。
这是一个简单的例子:
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
要浏览 Nix primops,请转到 15.5. Built-in Functions in the Nix manual (or see the docs of the unstable branch)。