【问题标题】:How does Nix's "callPackage" call functions defined without an ellipsis?Nix 的“callPackage”如何调用没有省略号定义的函数?
【发布时间】:2017-09-06 19:48:27
【问题描述】:

要调用使用集合解构的 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 时,它设法调用这些函数并仅将它们需要的参数传递给它们。这是如何实现的?

【问题讨论】:

标签: nix nixpkgs


【解决方案1】:

有一个反射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,请转到 Nix manual 中的 15.5. Built-in Functions(或查看 the docs of the unstable branch)。

【讨论】:

  • 最初我在上面的编辑中添加了“__functionArgs is the same as builtins.functionArgs”这一行,因为在nix repl中两者都评估为«primop»,但@ 987654325@ 让我不确定那句话。 (链接也显示setFunctionArgs,因为我无法理解它看似圆形的定义。)__intersectAttrsbuiltins.intersectAttrs 也是如此。
  • @toraritte 它们是相同的,只是 lib.nix 添加 __functionArgs attr 来模仿 __functionArgs 内置。它曾经将实际的 __functionArgs 结果“传递”给消费者,因为内置的 __functionArgs 仅适用于最顶层的函数 args。是的,心灵包装
猜你喜欢
  • 2019-09-01
  • 2020-05-24
  • 1970-01-01
  • 2012-10-28
  • 1970-01-01
  • 2021-02-25
  • 1970-01-01
  • 1970-01-01
  • 2016-02-15
相关资源
最近更新 更多