diff options
Diffstat (limited to 'doc/manual/expressions/language-constructs.xml')
-rw-r--r-- | doc/manual/expressions/language-constructs.xml | 408 |
1 files changed, 0 insertions, 408 deletions
diff --git a/doc/manual/expressions/language-constructs.xml b/doc/manual/expressions/language-constructs.xml deleted file mode 100644 index e1c589f61..000000000 --- a/doc/manual/expressions/language-constructs.xml +++ /dev/null @@ -1,408 +0,0 @@ -<section xmlns="http://docbook.org/ns/docbook" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:xi="http://www.w3.org/2001/XInclude" - version="5.0" - xml:id="sec-constructs"> - -<title>Language Constructs</title> - -<section><title>Recursive sets</title> - -<para>Recursive sets are just normal sets, but the attributes can -refer to each other. For example, - -<programlisting> -rec { - x = y; - y = 123; -}.x -</programlisting> - -evaluates to <literal>123</literal>. Note that without -<literal>rec</literal> the binding <literal>x = y;</literal> would -refer to the variable <varname>y</varname> 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.</para> - -<para>Recursive sets of course introduce the danger of infinite -recursion. For example, the expression - -<programlisting> -rec { - x = y; - y = x; -}.x</programlisting> - -will crash with an <literal>infinite recursion encountered</literal> -error message.</para> - -</section> - - -<section xml:id="sect-let-expressions"><title>Let-expressions</title> - -<para>A let-expression allows you to define local variables for an -expression. For instance, - -<programlisting> -let - x = "foo"; - y = "bar"; -in x + y</programlisting> - -evaluates to <literal>"foobar"</literal>. - -</para> - -</section> - - -<section><title>Inheriting attributes</title> - -<para>When defining a set or in a let-expression 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 -<literal>inherit</literal> keyword. For instance, - -<programlisting> -let x = 123; in -{ inherit x; - y = 456; -}</programlisting> - -is equivalent to - -<programlisting> -let x = 123; in -{ x = x; - y = 456; -}</programlisting> - -and both evaluate to <literal>{ x = 123; y = 456; }</literal>. (Note that -this works because <varname>x</varname> is added to the lexical scope -by the <literal>let</literal> construct.) It is also possible to -inherit attributes from another set. For instance, in this fragment -from <filename>all-packages.nix</filename>, - -<programlisting> - graphviz = (import ../tools/graphics/graphviz) { - inherit fetchurl stdenv libpng libjpeg expat x11 yacc; - inherit (xlibs) libXaw; - }; - - xlibs = { - libX11 = ...; - libXaw = ...; - ... - } - - libpng = ...; - libjpg = ...; - ...</programlisting> - -the set used in the function call to the function defined in -<filename>../tools/graphics/graphviz</filename> inherits a number of -variables from the surrounding scope (<varname>fetchurl</varname> -... <varname>yacc</varname>), but also inherits -<varname>libXaw</varname> (the X Athena Widgets) from the -<varname>xlibs</varname> (X11 client-side libraries) set.</para> - -<para> -Summarizing the fragment - -<programlisting> -... -inherit x y z; -inherit (src-set) a b c; -...</programlisting> - -is equivalent to - -<programlisting> -... -x = x; y = y; z = z; -a = src-set.a; b = src-set.b; c = src-set.c; -...</programlisting> - -when used while defining local variables in a let-expression or -while defining a set.</para> - -</section> - - -<section xml:id="ss-functions"><title>Functions</title> - -<para>Functions have the following form: - -<programlisting> -<emphasis>pattern</emphasis>: <emphasis>body</emphasis></programlisting> - -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:</para> - -<itemizedlist> - - - <listitem><para>If a pattern is a single identifier, then the - function matches any argument. Example: - - <programlisting> -let negate = x: !x; - concat = x: y: x + y; -in if negate true then concat "foo" "bar" else ""</programlisting> - - Note that <function>concat</function> 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., - - <programlisting> -map (concat "foo") [ "bar" "bla" "abc" ]</programlisting> - - evaluates to <literal>[ "foobar" "foobla" - "fooabc" ]</literal>.</para></listitem> - - - <listitem><para>A <emphasis>set pattern</emphasis> of the form - <literal>{ name1, name2, …, nameN }</literal> matches a set - containing the listed attributes, and binds the values of those - attributes to variables in the function body. For example, the - function - -<programlisting> -{ x, y, z }: z + y + x</programlisting> - - can only be called with a set containing exactly the attributes - <varname>x</varname>, <varname>y</varname> and - <varname>z</varname>. No other attributes are allowed. If you want - to allow additional arguments, you can use an ellipsis - (<literal>...</literal>): - -<programlisting> -{ x, y, z, ... }: z + y + x</programlisting> - - This works on any set that contains at least the three named - attributes.</para> - - <para>It is possible to provide <emphasis>default values</emphasis> - for attributes, in which case they are allowed to be missing. A - default value is specified by writing - <literal><emphasis>name</emphasis> ? - <emphasis>e</emphasis></literal>, where - <emphasis>e</emphasis> is an arbitrary expression. For example, - -<programlisting> -{ x, y ? "foo", z ? "bar" }: z + y + x</programlisting> - - specifies a function that only requires an attribute named - <varname>x</varname>, but optionally accepts <varname>y</varname> - and <varname>z</varname>.</para></listitem> - - - <listitem><para>An <literal>@</literal>-pattern provides a means of referring - to the whole value being matched: - -<programlisting> args@{ x, y, z, ... }: z + y + x + args.a</programlisting> - -but can also be written as: - -<programlisting> { x, y, z, ... } @ args: z + y + x + args.a</programlisting> - - Here <varname>args</varname> is bound to the entire argument, which - is further matched against the pattern <literal>{ x, y, z, - ... }</literal>. <literal>@</literal>-pattern makes mainly sense with an - ellipsis(<literal>...</literal>) as you can access attribute names as - <literal>a</literal>, using <literal>args.a</literal>, which was given as an - additional attribute to the function. - </para> - - <warning> - <para> - The <literal>args@</literal> expression is bound to the argument passed to the function which - means that attributes with defaults that aren't explicitly specified in the function call - won't cause an evaluation error, but won't exist in <literal>args</literal>. - </para> - <para> - For instance -<programlisting> -let - function = args@{ a ? 23, ... }: args; -in - function {} -</programlisting> - will evaluate to an empty attribute set. - </para> - </warning></listitem> - -</itemizedlist> - -<para>Note that functions do not have names. If you want to give them -a name, you can bind them to an attribute, e.g., - -<programlisting> -let concat = { x, y }: x + y; -in concat { x = "foo"; y = "bar"; }</programlisting> - -</para> - -</section> - - -<section><title>Conditionals</title> - -<para>Conditionals look like this: - -<programlisting> -if <emphasis>e1</emphasis> then <emphasis>e2</emphasis> else <emphasis>e3</emphasis></programlisting> - -where <emphasis>e1</emphasis> is an expression that should -evaluate to a Boolean value (<literal>true</literal> or -<literal>false</literal>).</para> - -</section> - - -<section><title>Assertions</title> - -<para>Assertions are generally used to check that certain requirements -on or between features and dependencies hold. They look like this: - -<programlisting> -assert <emphasis>e1</emphasis>; <emphasis>e2</emphasis></programlisting> - -where <emphasis>e1</emphasis> is an expression that should -evaluate to a Boolean value. If it evaluates to -<literal>true</literal>, <emphasis>e2</emphasis> is returned; -otherwise expression evaluation is aborted and a backtrace is printed.</para> - -<para>Here is a Nix expression for the Subversion package that shows -how assertions can be used:.</para> - -<programlisting> -{ 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; ④ - ... -}</programlisting> - -<para>The points of interest are:</para> - -<orderedlist> - - <listitem> - <para>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 - <varname>localServer</varname> argument set to - <literal>true</literal> but the <varname>db4</varname> argument - set to <literal>null</literal>, then the evaluation fails.</para> - </listitem> - - <listitem> - <para>This is a more subtle condition: if Subversion is built with - Apache (<literal>httpServer</literal>) 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.</para> - </listitem> - - <listitem> - <para>This assertion says that in order for Subversion to have SSL - support (so that it can access <literal>https</literal> URLs), an - OpenSSL library must be passed. Additionally, it says that - <emphasis>if</emphasis> 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.)</para> - </listitem> - - <listitem> - <para>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-<literal>null</literal> value was passed. - This prevents an unnecessary rebuild of Subversion if OpenSSL - changes.</para> - </listitem> - -</orderedlist> - -</section> - - - -<section><title>With-expressions</title> - -<para>A <emphasis>with-expression</emphasis>, - -<programlisting> -with <emphasis>e1</emphasis>; <emphasis>e2</emphasis></programlisting> - -introduces the set <emphasis>e1</emphasis> into the lexical -scope of the expression <emphasis>e2</emphasis>. For instance, - -<programlisting> -let as = { x = "foo"; y = "bar"; }; -in with as; x + y</programlisting> - -evaluates to <literal>"foobar"</literal> since the -<literal>with</literal> adds the <varname>x</varname> and -<varname>y</varname> attributes of <varname>as</varname> to the -lexical scope in the expression <literal>x + y</literal>. The most -common use of <literal>with</literal> is in conjunction with the -<function>import</function> function. E.g., - -<programlisting> -with (import ./definitions.nix); ...</programlisting> - -makes all attributes defined in the file -<filename>definitions.nix</filename> available as if they were defined -locally in a <literal>let</literal>-expression.</para> - -<para>The bindings introduced by <literal>with</literal> do not shadow bindings -introduced by other means, e.g. - -<programlisting> -let a = 3; in with { a = 1; }; let a = 4; in with { a = 2; }; ...</programlisting> - -establishes the same scope as - -<programlisting> -let a = 1; in let a = 2; in let a = 3; in let a = 4; in ...</programlisting> - -</para> - -</section> - - -<section><title>Comments</title> - -<para>Comments can be single-line, started with a <literal>#</literal> -character, or inline/multi-line, enclosed within <literal>/* -... */</literal>.</para> - -</section> - - -</section> |