Наследование атрибутов из другого набора в языке выражений Nix

В разделе наследования атрибутов руководства Nix есть

graphviz = (import ../tools/graphics/graphviz) {
  inherit fetchurl stdenv libpng libjpeg expat x11 yacc;
  inherit (xlibs) libXaw;
};

xlibs = {
  libX11 = ...;
  libXaw = ...;
  ...
}

libpng = ...;
libjpg = ...;
...

Что делают скобки вокруг import ... (т.е. (import ../tools/graphics/graphviz))? Кроме того, что делают скобки в inherit (xlibs) libXaw;?


person Ben    schedule 17.12.2016    source источник


Ответы (1)


xlibs находится в той же области видимости, что и graphviz, но libXaw - нет, потому что находится внутри набора xlibs. Таким образом, чтобы передать его в качестве аргумента функции graphviz, вам необходимо явно inherit (xlibs) libXaw. Такое поведение, обозначенное скобками, уникально для ключевого слова inherit.

Скобки в (import ../tools/graphics/graphviz) - это просто общепринятое соглашение для обозначения порядка оценки. import - это функция, которая принимает единственный аргумент path. Файл в ../tools/graphics/graphviz содержит единственную функцию, которая принимает набор атрибутов в качестве аргумента. Таким образом, скобки обозначают, что порядок оценки должен быть следующим: (1) импортировать функцию в path, затем (2) применить набор атрибутов {...} к этой функции.


Изменить: @danbst указал, что в этом случае скобки в import ../tools/graphics/graphviz не нужны. Причина этого в том, что оценка import ../tools/graphics/graphviz возвращает функцию, которая затем вызывается с набором { ... }.

Необходимость скобок можно продемонстрировать, используя те же значения в качестве аргументов для этой функции typesOfArgs = one: two: with builtins; "${typeOf one} and ${typeOf two}", которая возвращает строку. typesOfArgs (import ../tools/graphics/graphviz) { } будет оцениваться как "lambda and set", но без скобок интерпретатор оценил бы typesOfArgs import ../tools/graphics/graphviz в "lambda and path", а затем попытался бы вызвать эту строку как функцию с аргументом { }, что привело бы к error: attempt to call something which is not a function but a string

Без скобок интерпретатор предположил бы, что вы хотите вызвать функцию import с двумя аргументами path и { ... }, что было бы ошибкой.

person brocking    schedule 20.12.2016
comment
Очень красивое объяснение. Спасибо! - person Ben; 21.12.2016