Inherit Attributes from Another Set in Nix Expression Language

4k views Asked by At

In Nix manual's Inheriting attributes section, we have

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

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

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

What do the brackets around import ... (i.e. (import ../tools/graphics/graphviz)) do? Also, what do the brackets in inherit (xlibs) libXaw; do?

1

There are 1 answers

1
brocking On BEST ANSWER

xlibs is in the same scope as graphviz but libXaw is not, because it's inside the xlibs set. So to be able to pass it as an argument to the graphviz function you need to explicitly inherit (xlibs) libXaw. That behaviour denoted by the brackets is unique to the inherit keyword.

The brackets in (import ../tools/graphics/graphviz) are simply the common convention for denoting order of evaluation. import is a function that accepts a single argument path. The file in ../tools/graphics/graphviz contains a single function that accepts a set of attributes as its argument. So the brackets denote that the order of evaluation should be (1) import the function in path then (2) apply the attribute set {...} to that function.


Edit: @danbst pointed out that in this case the brackets in import ../tools/graphics/graphviz aren't needed. The reason for this is that evaluating import ../tools/graphics/graphviz returns a function which is then called with the set { ... }.

The necessity of the brackets can be demonstrated by using the same values as arguments for this function typesOfArgs = one: two: with builtins; "${typeOf one} and ${typeOf two}" which returns a string. typesOfArgs (import ../tools/graphics/graphviz) { } would evaluate to "lambda and set" but without the brackets the interpreter would evaluate typesOfArgs import ../tools/graphics/graphviz to "lambda and path" and then try to call that string as a function with the argument { } which would result in error: attempt to call something which is not a function but a string

Without the brackets the interpreter would assume you want to call the function import with the 2 arguments path and { ... }, which would be an error.