From 8901acc97664aa8ebf687ee904428aa57a5192be Mon Sep 17 00:00:00 2001 From: Mikey Ariel Date: Wed, 27 Aug 2014 18:41:09 +0200 Subject: Restructuring the Nix manual --- doc/manual/expressions/language-constructs.xml | 344 +++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 doc/manual/expressions/language-constructs.xml (limited to 'doc/manual/expressions/language-constructs.xml') diff --git a/doc/manual/expressions/language-constructs.xml b/doc/manual/expressions/language-constructs.xml new file mode 100644 index 000000000000..ddb3498946b7 --- /dev/null +++ b/doc/manual/expressions/language-constructs.xml @@ -0,0 +1,344 @@ +
+ +Language Constructs + +Recursive sets + +Recursive sets are just normal sets, but the attributes can +refer to each other. For example, + + +rec { + x = y; + y = 123; +}.x + + +evaluates to 123. Note that without +rec the binding x = y; would +refer to the variable y in the surrounding scope, +if one exists, and would be invalid if no such variable exists. That +is, in a normal (non-recursive) set, attributes are not added to the +lexical scope; in a recursive set, they are. + +Recursive sets of course introduce the danger of infinite +recursion. For example, + + +rec { + x = y; + y = x; +}.x + +does not terminateActually, Nix detects infinite +recursion in this case and aborts (infinite recursion +encountered).. + + + + +Let-expressions + +A let-expression allows you define local variables for an +expression. For instance, + + +let + x = "foo"; + y = "bar"; +in x + y + +evaluates to "foobar". + + + + + + +Inheriting attributes + +When defining a set it is often convenient to copy variables +from the surrounding lexical scope (e.g., when you want to propagate +attributes). This can be shortened using the +inherit keyword. For instance, + + +let x = 123; in +{ inherit x; + y = 456; +} + +evaluates to { x = 123; y = 456; }. (Note that +this works because x is added to the lexical scope +by the let construct.) It is also possible to +inherit attributes from another set. For instance, in this fragment +from all-packages.nix, + + + graphviz = (import ../tools/graphics/graphviz) { + inherit fetchurl stdenv libpng libjpeg expat x11 yacc; + inherit (xlibs) libXaw; + }; + + xlibs = { + libX11 = ...; + libXaw = ...; + ... + } + + libpng = ...; + libjpg = ...; + ... + +the set used in the function call to the function defined in +../tools/graphics/graphviz inherits a number of +variables from the surrounding scope (fetchurl +... yacc), but also inherits +libXaw (the X Athena Widgets) from the +xlibs (X11 client-side libraries) set. + + + + +Functions + +Functions have the following form: + + +pattern: body + +The pattern specifies what the argument of the function must look +like, and binds variables in the body to (parts of) the +argument. There are three kinds of patterns: + + + + + If a pattern is a single identifier, then the + function matches any argument. Example: + + +let negate = x: !x; + concat = x: y: x + y; +in if negate true then concat "foo" "bar" else "" + + Note that concat is a function that takes one + argument and returns a function that takes another argument. This + allows partial parameterisation (i.e., only filling some of the + arguments of a function); e.g., + + +map (concat "foo") [ "bar" "bla" "abc" ] + + evaluates to [ "foobar" "foobla" + "fooabc" ]. + + + A set pattern of the form + { name1, name2, …, nameN } matches a set + containing the listed attributes, and binds the values of those + attributes to variables in the function body. For example, the + function + + +{ x, y, z }: z + y + x + + can only be called with a set containing exactly the attributes + x, y and + z. No other attributes are allowed. If you want + to allow additional arguments, you can use an ellipsis + (...): + + +{ x, y, z, ... }: z + y + x + + This works on any set that contains at least the three named + attributes. + + It is possible to provide default values + for attributes, in which case they are allowed to be missing. A + default value is specified by writing + name ? + e, where + e is an arbitrary expression. For example, + + +{ x, y ? "foo", z ? "bar" }: z + y + x + + specifies a function that only requires an attribute named + x, but optionally accepts y + and z. + + + An @-pattern provides a means of referring + to the whole value being matched: + + +args@{ x, y, z, ... }: z + y + x + args.a + + Here args is bound to the entire argument, which + is further matched against the pattern { x, y, z, + ... }. + + + + +Note that functions do not have names. If you want to give them +a name, you can bind them to an attribute, e.g., + + +let concat = { x, y }: x + y; +in concat { x = "foo"; y = "bar"; } + + + + + + +Conditionals + +Conditionals look like this: + + +if e1 then e2 else e3 + +where e1 is an expression that should +evaluate to a Boolean value (true or +false). + + + + +Assertions + +Assertions are generally used to check that certain requirements +on or between features and dependencies hold. They look like this: + + +assert e1; e2 + +where e1 is an expression that should +evaluate to a Boolean value. If it evaluates to +true, e2 is returned; +otherwise expression evaluation is aborted and a backtrace is printed. + +Nix expression for Subversion + +{ localServer ? false +, httpServer ? false +, sslSupport ? false +, pythonBindings ? false +, javaSwigBindings ? false +, javahlBindings ? false +, stdenv, fetchurl +, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null +}: + +assert localServer -> db4 != null; +assert httpServer -> httpd != null && httpd.expat == expat; +assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl); +assert pythonBindings -> swig != null && swig.pythonSupport; +assert javaSwigBindings -> swig != null && swig.javaSupport; +assert javahlBindings -> j2sdk != null; + +stdenv.mkDerivation { + name = "subversion-1.1.1"; + ... + openssl = if sslSupport then openssl else null; + ... +} + + + show how assertions are +used in the Nix expression for Subversion. + + + + + This assertion states that if Subversion is to have support + for local repositories, then Berkeley DB is needed. So if the + Subversion function is called with the + localServer argument set to + true but the db4 argument + set to null, then the evaluation fails. + + + + This is a more subtle condition: if Subversion is built with + Apache (httpServer) support, then the Expat + library (an XML library) used by Subversion should be same as the + one used by Apache. This is because in this configuration + Subversion code ends up being linked with Apache code, and if the + Expat libraries do not match, a build- or runtime link error or + incompatibility might occur. + + + + This assertion says that in order for Subversion to have SSL + support (so that it can access https URLs), an + OpenSSL library must be passed. Additionally, it says that + if Apache support is enabled, then Apache's + OpenSSL should match Subversion's. (Note that if Apache support + is not enabled, we don't care about Apache's OpenSSL.) + + + + The conditional here is not really related to assertions, + but is worth pointing out: it ensures that if SSL support is + disabled, then the Subversion derivation is not dependent on + OpenSSL, even if a non-null value was passed. + This prevents an unnecessary rebuild of Subversion if OpenSSL + changes. + + + + + + + + +With-expressions + +A with-expression, + + +with e1; e2 + +introduces the set e1 into the lexical +scope of the expression e2. For instance, + + +let as = { x = "foo"; y = "bar"; }; +in with as; x + y + +evaluates to "foobar" since the +with adds the x and +y attributes of as to the +lexical scope in the expression x + y. The most +common use of with is in conjunction with the +import function. E.g., + + +with (import ./definitions.nix); ... + +makes all attributes defined in the file +definitions.nix available as if they were defined +locally in a rec-expression. + + + + +Comments + +Comments can be single-line, started with a # +character, or inline/multi-line, enclosed within /* +... */. + + + + +
\ No newline at end of file -- cgit 1.4.1