为什么 `functionArgs` 实现了两次? (即,作为 primop 并在 `lib` 中)
Why is `functionArgs` implemented twice? (i.e, as a primop and in `lib`)
试图理解 callPackage
,所以查找 its implementation where it uses lib.functionArgs
(source), but there is already a builtins.functionArgs
primop, an alias of __functionArgs
(implemented in C)。
lib.functionArgs
定义为
/* Extract the expected function arguments from a function.
This works both with nix-native { a, b ? foo, ... }: style
functions and functions with args set with 'setFunctionArgs'. It
has the same return type and semantics as builtins.functionArgs.
setFunctionArgs : (a → b) → Map String Bool.
*/
functionArgs = f: f.__functionArgs or (builtins.functionArgs f);
并且上面的 __functionArgs
属性来自 setFunctionArgs
(source):
/* Add metadata about expected function arguments to a function.
The metadata should match the format given by
builtins.functionArgs, i.e. a set from expected argument to a bool
representing whether that argument has a default or not.
setFunctionArgs : (a → b) → Map String Bool → (a → b)
This function is necessary because you can't dynamically create a
function of the { a, b ? foo, ... }: format, but some facilities
like callPackage expect to be able to query expected arguments.
*/
setFunctionArgs = f: args:
{
__functor = self: f;
__functionArgs = args;
};
我理解 setFunctionArgs
的作用,其声明上方的注释说明了为什么有必要,但我无法理解;该句子的两个子句都很清楚,但不确定第一个语句如何阻止第二个语句的实现(没有 setFunctionArgs
,即)。
,
lib.nix
adds __functionArgs
attr to mimic __functionArgs
builtin. It
used to "pass" actual __functionArgs
result down to consumers, because
builtin __functionArgs
only works on top-most function args
但不确定“消费者”是什么,无法解压最后一个子句(即,“builtin __functionArgs
仅适用于最顶层函数 args”)。这是对 Nix 函数被柯里化这一事实的引用吗?
nix-repl> g = a: { b, c }: "lofa"
nix-repl> builtins.functionArgs g
{ }
?
lib.functionArgs
也没有解决这个问题,但我现在可能偏离了轨道。
自述
__functor
记录在 Sets 下的 Nix 手册中。
$ nix repl '<nixpkgs>'
Welcome to Nix version 2.3.6. Type :? for help.
Loading '<nixpkgs>'...
Added 11530 variables.
nix-repl> f = { a ? 7, b }: a + b
nix-repl> set_f = lib.setFunctionArgs f { b = 9; }
nix-repl> set_f
{ __functionArgs = { ... }; __functor = «lambda @ /nix/store/16blhmppp9k6apz41gjlgr0arp88awyb-nixos-20.03.3258.86fa45b0ff1/nixos/lib/trivial.nix:318:19»; }
nix-repl> set_f.__functionArgs
{ b = 9; }
nix-repl> set_f set_f.__functionArgs
16
nix-repl> set_f { a = 27; b = 9; }
36
lib.functionArgs
包装 builtins.functionArgs
以提供对通用函数的反射访问。
这支持反射 builtins.functionArgs
:
f = { a, b, c }: #...
现在考虑同一个函数的eta abstraction:
f' = attrs: f attrs
这不支持 builtins.functionArgs
的反射。使用 setFunctionArgs
,您可以恢复该信息,只要您还使用 lib.functionArgs
。
我建议避免反射,因为我看到用它实现的所有东西都可以在没有它的情况下实现。它扩展了函数的定义,以包括通常应被视为实现细节的内容。
无论如何,主要动机似乎是 callPackage
,如果您更改所有包以添加 ...
,则 可以 通过正常的 attrset 操作来实现,如 { lib, stdenv, ... }:
].我确实对函数反射这个错误特性抱有病态的兴趣,所以如果有人发现另一个用例,请发表评论。
试图理解 callPackage
,所以查找 its implementation where it uses lib.functionArgs
(source), but there is already a builtins.functionArgs
primop, an alias of __functionArgs
(implemented in C)。
lib.functionArgs
定义为
/* Extract the expected function arguments from a function.
This works both with nix-native { a, b ? foo, ... }: style
functions and functions with args set with 'setFunctionArgs'. It
has the same return type and semantics as builtins.functionArgs.
setFunctionArgs : (a → b) → Map String Bool.
*/
functionArgs = f: f.__functionArgs or (builtins.functionArgs f);
并且上面的 __functionArgs
属性来自 setFunctionArgs
(source):
/* Add metadata about expected function arguments to a function.
The metadata should match the format given by
builtins.functionArgs, i.e. a set from expected argument to a bool
representing whether that argument has a default or not.
setFunctionArgs : (a → b) → Map String Bool → (a → b)
This function is necessary because you can't dynamically create a
function of the { a, b ? foo, ... }: format, but some facilities
like callPackage expect to be able to query expected arguments.
*/
setFunctionArgs = f: args:
{
__functor = self: f;
__functionArgs = args;
};
我理解 setFunctionArgs
的作用,其声明上方的注释说明了为什么有必要,但我无法理解;该句子的两个子句都很清楚,但不确定第一个语句如何阻止第二个语句的实现(没有 setFunctionArgs
,即)。
lib.nix
adds__functionArgs
attr to mimic__functionArgs
builtin. It used to "pass" actual__functionArgs
result down to consumers, because builtin__functionArgs
only works on top-most function args
但不确定“消费者”是什么,无法解压最后一个子句(即,“builtin __functionArgs
仅适用于最顶层函数 args”)。这是对 Nix 函数被柯里化这一事实的引用吗?
nix-repl> g = a: { b, c }: "lofa"
nix-repl> builtins.functionArgs g
{ }
?
lib.functionArgs
也没有解决这个问题,但我现在可能偏离了轨道。
自述
__functor
记录在 Sets 下的 Nix 手册中。
$ nix repl '<nixpkgs>'
Welcome to Nix version 2.3.6. Type :? for help.
Loading '<nixpkgs>'...
Added 11530 variables.
nix-repl> f = { a ? 7, b }: a + b
nix-repl> set_f = lib.setFunctionArgs f { b = 9; }
nix-repl> set_f
{ __functionArgs = { ... }; __functor = «lambda @ /nix/store/16blhmppp9k6apz41gjlgr0arp88awyb-nixos-20.03.3258.86fa45b0ff1/nixos/lib/trivial.nix:318:19»; }
nix-repl> set_f.__functionArgs
{ b = 9; }
nix-repl> set_f set_f.__functionArgs
16
nix-repl> set_f { a = 27; b = 9; }
36
lib.functionArgs
包装 builtins.functionArgs
以提供对通用函数的反射访问。
这支持反射 builtins.functionArgs
:
f = { a, b, c }: #...
现在考虑同一个函数的eta abstraction:
f' = attrs: f attrs
这不支持 builtins.functionArgs
的反射。使用 setFunctionArgs
,您可以恢复该信息,只要您还使用 lib.functionArgs
。
我建议避免反射,因为我看到用它实现的所有东西都可以在没有它的情况下实现。它扩展了函数的定义,以包括通常应被视为实现细节的内容。
无论如何,主要动机似乎是 callPackage
,如果您更改所有包以添加 ...
,则 可以 通过正常的 attrset 操作来实现,如 { lib, stdenv, ... }:
].我确实对函数反射这个错误特性抱有病态的兴趣,所以如果有人发现另一个用例,请发表评论。