about summary refs log tree commit diff
path: root/doc/manual/builtins.xml
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2007-10-22T12·58+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2007-10-22T12·58+0000
commit35ac16e75e1fb7c948adecd64904f40b96d1d8fb (patch)
treeb8cd9c99590dece0f826218441d734a1bde4e009 /doc/manual/builtins.xml
parent1db187ff690e6673433eb073088fe5169e12a4d2 (diff)
* Move list of built-in functions to a separate file.
Diffstat (limited to 'doc/manual/builtins.xml')
-rw-r--r--doc/manual/builtins.xml588
1 files changed, 588 insertions, 0 deletions
diff --git a/doc/manual/builtins.xml b/doc/manual/builtins.xml
new file mode 100644
index 0000000000..8f9272505c
--- /dev/null
+++ b/doc/manual/builtins.xml
@@ -0,0 +1,588 @@
+<section xmlns="http://docbook.org/ns/docbook"
+              xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<title>Built-in functions</title>
+
+
+<para>This section lists the functions and constants built into the
+Nix expression evaluator.  (The built-in function
+<function>derivation</function> is discussed above.)  Some built-ins,
+such as <function>derivation</function>, are always in scope of every
+Nix expression; you can just access them right away.  But to prevent
+polluting the namespace too much, most built-ins are not in scope.
+Instead, you can access them through the <varname>builtins</varname>
+built-in value, which is an attribute set that contains all built-in
+functions and values.  For instance, <function>derivation</function>
+is also available as <function>builtins.derivation</function>.</para>
+
+
+<variablelist >
+
+  
+  <varlistentry><term><function>abort</function> <replaceable>s</replaceable></term>
+
+    <listitem><para>Abort Nix expression evaluation, print error
+    message <replaceable>s</replaceable>.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.add</function>
+  <replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
+
+    <listitem><para>Return the sum of the integers
+    <replaceable>e1</replaceable> and
+    <replaceable>e2</replaceable>.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.attrNames</function>
+  <replaceable>attrs</replaceable></term>
+
+    <listitem><para>Return the names of the attributes in the
+    attribute set <replaceable>attrs</replaceable> in a sorted list.
+    For instance, <literal>builtins.attrNames {y = 1; x =
+    "foo";}</literal> evaluates to <literal>["x" "y"]</literal>.
+    There is no built-in function <function>attrValues</function>, but
+    you can easily define it yourself:
+
+<programlisting>
+attrValues = attrs: map (name: builtins.getAttr name attrs) (builtins.attrNames attrs);</programlisting>
+
+    </para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>baseNameOf</function> <replaceable>s</replaceable></term>
+
+    <listitem><para>Return the <emphasis>base name</emphasis> of the
+    string <replaceable>s</replaceable>, that is, everything following
+    the final slash in the string.  This is similar to the GNU
+    <command>basename</command> command.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><varname>builtins</varname></term>
+
+    <listitem><para>The attribute set <varname>builtins</varname>
+    contains all the built-in functions and values.  You can use
+    <varname>builtins</varname> to test for the availability of
+    features in the Nix installation, e.g.,
+
+<programlisting>
+if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
+
+    This allows a Nix expression to fall back gracefully on older Nix
+    installations that don’t have the desired built-in function.
+    However, in that case you should not write
+
+<programlisting>
+if builtins ? getEnv then __getEnv "PATH" else ""</programlisting>
+
+    This Nix expression will trigger an “undefined variable” error on
+    older Nix versions since <function>__getEnv</function> doesn’t
+    exist.  <literal>builtins.getEnv</literal>, on the other hand, is
+    safe since <literal>builtins</literal> always exists and attribute
+    selection is lazy, so it’s only performed if the test
+    succeeds.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry
+  xml:id='builtin-currentSystem'><term><varname>builtins.currentSystem</varname></term>
+
+    <listitem><para>The built-in value <varname>currentSystem</varname>
+    evaluates to the Nix platform identifier for the Nix installation
+    on which the expression is being evaluated, such as
+    <literal>"i686-linux"</literal> or
+    <literal>"powerpc-darwin"</literal>.</para></listitem>
+
+  </varlistentry>
+
+
+  <!--
+  <varlistentry><term><function>currentTime</function></term>
+
+    <listitem><para>The built-in value <varname>currentTime</varname>
+    returns the current system time in seconds since 00:00:00 1/1/1970
+    UTC.  Due to the evaluation model of Nix expressions
+    (<emphasis>maximal laziness</emphasis>), it always yields the same
+    value within an execution of Nix.</para></listitem>
+
+  </varlistentry>
+  -->
+
+  
+  <!--
+  <varlistentry><term><function>dependencyClosure</function></term>
+
+    <listitem><para>TODO</para></listitem>
+
+  </varlistentry>
+  -->
+
+  
+  <varlistentry><term><function>derivation</function>
+  <replaceable>attrs</replaceable></term>
+
+    <listitem><para><function>derivation</function> is described in
+    <xref linkend='ssec-derivation' />.</para></listitem>
+
+  </varlistentry>
+
+
+  <varlistentry><term><function>dirOf</function> <replaceable>s</replaceable></term>
+
+    <listitem><para>Return the directory part of the string
+    <replaceable>s</replaceable>, that is, everything before the final
+    slash in the string.  This is similar to the GNU
+    <command>dirname</command> command.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.getAttr</function>
+  <replaceable>s</replaceable> <replaceable>attrs</replaceable></term>
+
+    <listitem><para><function>getAttr</function> returns the attribute
+    named <replaceable>s</replaceable> from the attribute set
+    <replaceable>attrs</replaceable>.  Evaluation aborts if the
+    attribute doesn’t exist.  This is a dynamic version of the
+    <literal>.</literal> operator, since <replaceable>s</replaceable>
+    is an expression rather than an identifier.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.getEnv</function>
+  <replaceable>s</replaceable></term>
+
+    <listitem><para><function>getEnv</function> returns the value of
+    the environment variable <replaceable>s</replaceable>, or an empty
+    string if the variable doesn’t exist.  This function should be
+    used with care, as it can introduce all sorts of nasty environment
+    dependencies in your Nix expression.</para>
+
+    <para><function>getEnv</function> is used in Nix Packages to
+    locate the file <filename>~/.nixpkgs/config.nix</filename>, which
+    contains user-local settings for Nix Packages.  (That is, it does
+    a <literal>getEnv "HOME"</literal> to locate the user’s home
+    directory.)</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.hasAttr</function>
+  <replaceable>s</replaceable> <replaceable>attrs</replaceable></term>
+
+    <listitem><para><function>hasAttr</function> returns
+    <literal>true</literal> if the attribute set
+    <replaceable>attrs</replaceable> has an attribute named
+    <replaceable>s</replaceable>, and <literal>false</literal>
+    otherwise.  This is a dynamic version of the <literal>?</literal>
+    operator, since <replaceable>s</replaceable> is an expression
+    rather than an identifier.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.head</function>
+  <replaceable>list</replaceable></term>
+
+    <listitem><para>Return the first element of a list; abort
+    evaluation if the argument isn’t a list or is an empty list.  You
+    can test whether a list is empty by comparing it with
+    <literal>[]</literal>.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>import</function>
+  <replaceable>path</replaceable></term>
+
+    <listitem><para>Load, parse and return the Nix expression in the
+    file <replaceable>path</replaceable>.  Evaluation aborts if the
+    file doesn’t exist or contains an incorrect Nix
+    expression.  <function>import</function> implements Nix’s module
+    system: you can put any Nix expression (such as an attribute set
+    or a function) in a separate file, and use it from Nix expressions
+    in other files.</para>
+
+    <para>A Nix expression loaded by <function>import</function> must
+    not contain any <emphasis>free variables</emphasis> (identifiers
+    that are not defined in the Nix expression itself and are not
+    built-in).  Therefore, it cannot refer to variables that are in
+    scope at the call site.  For instance, if you have a calling
+    expression
+    
+<programlisting>
+rec {
+  x = 123;
+  y = import ./foo.nix;
+}</programlisting>
+
+    then the following <filename>foo.nix</filename> will give an
+    error:
+
+<programlisting>
+x + 456</programlisting>
+
+    since <varname>x</varname> is not in scope in
+    <filename>foo.nix</filename>.  If you want <varname>x</varname>
+    to be available in <filename>foo.nix</filename>, you should pass
+    it as a function argument:
+
+<programlisting>
+rec {
+  x = 123;
+  y = import ./foo.nix x;
+}</programlisting>
+
+    and
+
+<programlisting>
+x: x + 456</programlisting>
+
+    (The function argument doesn’t have to be called
+    <varname>x</varname> in <filename>foo.nix</filename>; any name
+    would work.)</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.isList</function>
+  <replaceable>e</replaceable></term>
+
+    <listitem><para>Return <literal>true</literal> if
+    <replaceable>e</replaceable> evaluates to a list, and
+    <literal>false</literal> otherwise.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>isNull</function>
+  <replaceable>e</replaceable></term>
+
+    <listitem><para>Return <literal>true</literal> if
+    <replaceable>e</replaceable> evaluates to <literal>null</literal>,
+    and <literal>false</literal> otherwise.</para>
+
+    <warning><para>This function is <emphasis>deprecated</emphasis>;
+    just write <literal>e == null</literal> instead.</para></warning>
+    
+    </listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.lessThan</function>
+  <replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
+
+    <listitem><para>Return <literal>true</literal> if the integer
+    <replaceable>e1</replaceable> is less than the integer
+    <replaceable>e2</replaceable>, and <literal>false</literal>
+    otherwise.  Evaluation aborts if either
+    <replaceable>e1</replaceable> or <replaceable>e2</replaceable>
+    does not evaluate to an integer.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>map</function>
+  <replaceable>f</replaceable> <replaceable>list</replaceable></term>
+
+    <listitem><para>Apply the function <replaceable>f</replaceable> to
+    each element in the list <replaceable>list</replaceable>.  For
+    example,
+
+<programlisting>
+map (x: "foo" + x) ["bar" "bla" "abc"]</programlisting>
+
+    evaluates to <literal>["foobar" "foobla"
+    "fooabc"]</literal>.</para></listitem>
+    
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.pathExists</function>
+  <replaceable>path</replaceable></term>
+
+    <listitem><para>Return <literal>true</literal> if the path
+    <replaceable>path</replaceable> exists, and
+    <literal>false</literal> otherwise.  One application of this
+    function is to conditionally include a Nix expression containing
+    user configuration:
+
+<programlisting>
+let
+  fileName = builtins.getEnv "CONFIG_FILE";
+  config =
+    if fileName != "" &amp;&amp; builtins.pathExists (builtins.toPath fileName)
+    then import (builtins.toPath fileName)
+    else { someSetting = false; }; <lineannotation># default configuration</lineannotation>
+in config.someSetting</programlisting>
+
+    (Note that <envar>CONFIG_FILE</envar> must be an absolute path for
+    this to work.)</para></listitem>
+
+  </varlistentry>
+
+
+  <!--
+  <varlistentry><term><function>relativise</function></term>
+
+    <listitem><para>TODO</para></listitem>
+
+  </varlistentry>
+  -->
+
+  
+  <varlistentry><term><function>removeAttrs</function>
+  <replaceable>attrs</replaceable> <replaceable>list</replaceable></term>
+
+    <listitem><para>Remove the attributes listed in
+    <replaceable>list</replaceable> from the attribute set
+    <replaceable>attrs</replaceable>.  The attributes don’t have to
+    exist in <replaceable>attrs</replaceable>. For instance,
+
+<screen>
+removeAttrs { x = 1; y = 2; z = 3; } ["a" "x" "z"]</screen>
+
+    evaluates to <literal>{y = 2;}</literal>.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.tail</function>
+  <replaceable>list</replaceable></term>
+
+    <listitem><para>Return the second to last elements of a list;
+    abort evaluation if the argument isn’t a list or is an empty
+    list.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry
+  xml:id='builtin-toFile'><term><function>builtins.toFile</function>
+  <replaceable>name</replaceable> <replaceable>s</replaceable></term>
+
+    <listitem><para>Store the string <replaceable>s</replaceable> in a
+    file in the Nix store and return its path.  The file has suffix
+    <replaceable>name</replaceable>.  This file can be used as an
+    input to derivations.  One application is to write builders
+    “inline”.  For instance, the following Nix expression combines
+    <xref linkend='ex-hello-nix' /> and <xref
+    linkend='ex-hello-builder' /> into one file:
+
+<programlisting>
+{stdenv, fetchurl, perl}:
+
+stdenv.mkDerivation {
+  name = "hello-2.1.1";
+  
+  builder = builtins.toFile "builder.sh" "
+    source $stdenv/setup
+
+    PATH=$perl/bin:$PATH
+
+    tar xvfz $src
+    cd hello-*
+    ./configure --prefix=$out
+    make
+    make install
+  ";
+
+  src = fetchurl {
+    url = http://nix.cs.uu.nl/dist/tarballs/hello-2.1.1.tar.gz;
+    md5 = "70c9ccf9fac07f762c24f2df2290784d";
+  };
+  inherit perl;
+}</programlisting>
+  
+    </para>
+
+    <para>It is even possible for one file to refer to another, e.g.,
+
+<programlisting>
+  builder = let
+    configFile = builtins.toFile "foo.conf" "
+      # This is some dummy configuration file.
+      <replaceable>...</replaceable>
+    ";
+  in builtins.toFile "builder.sh" "
+    source $stdenv/setup
+    <replaceable>...</replaceable>
+    cp ${configFile} $out/etc/foo.conf
+  ";</programlisting>
+
+    Note that <literal>${configFile}</literal> is an antiquotation
+    (see <xref linkend='ssec-values' />), so the result of the
+    expression <literal>configFile</literal> (i.e., a path like
+    <filename>/nix/store/m7p7jfny445k...-foo.conf</filename>) will be
+    spliced into the resulting string.</para>
+
+    <para>It is however <emphasis>not</emphasis> allowed to have files
+    mutually referring to each other, like so:
+
+<programlisting>
+let
+  foo = builtins.toFile "foo" "...${bar}...";
+  bar = builtins.toFile "bar" "...${foo}...";
+in foo</programlisting>
+
+    This is not allowed because it would cause a cyclic dependency in
+    the computation of the cryptographic hashes for
+    <varname>foo</varname> and <varname>bar</varname>.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>builtins.toPath</function> <replaceable>s</replaceable></term>
+
+    <listitem><para>Convert the string value
+    <replaceable>s</replaceable> into a path value.  The string
+    <replaceable>s</replaceable> must represent an absolute path
+    (i.e., must start with <literal>/</literal>).  The path need not
+    exist.  The resulting path is canonicalised, e.g.,
+    <literal>builtins.toPath "//foo/xyzzy/../bar/"</literal> returns
+    <literal>/foo/bar</literal>.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry><term><function>toString</function> <replaceable>e</replaceable></term>
+
+    <listitem><para>Convert the expression
+    <replaceable>e</replaceable> to a string.
+    <replaceable>e</replaceable> can be a string (in which case
+    <function>toString</function> is a no-op) or a path (e.g.,
+    <literal>toString /foo/bar</literal> yields
+    <literal>"/foo/bar"</literal>.</para></listitem>
+
+  </varlistentry>
+
+  
+  <varlistentry xml:id='builtin-toXML'><term><function>builtins.toXML</function> <replaceable>e</replaceable></term>
+
+    <listitem><para>Return a string containing an XML representation
+    of <replaceable>e</replaceable>.  The main application for
+    <function>toXML</function> is to communicate information with the
+    builder in a more structured format than plain environment
+    variables.</para>
+
+    <!-- TODO: more formally describe the schema of the XML
+    representation -->
+
+    <para><xref linkend='ex-toxml' /> shows an example where this is
+    the case.  The builder is supposed to generate the configuration
+    file for a <link xlink:href='http://jetty.mortbay.org/'>Jetty
+    servlet container</link>.  A servlet container contains a number
+    of servlets (<filename>*.war</filename> files) each exported under
+    a specific URI prefix.  So the servlet configuration is a list of
+    attribute sets containing the <varname>path</varname> and
+    <varname>war</varname> of the servlet (<xref
+    linkend='ex-toxml-co-servlets' />).  This kind of information is
+    difficult to communicate with the normal method of passing
+    information through an environment variable, which just
+    concatenates everything together into a string (which might just
+    work in this case, but wouldn’t work if fields are optional or
+    contain lists themselves).  Instead the Nix expression is
+    converted to an XML representation with
+    <function>toXML</function>, which is unambiguous and can easily be
+    processed with the appropriate tools.  For instance, in the
+    example an XSLT stylesheet (<xref linkend='ex-toxml-co-stylesheet'
+    />) is applied to it (<xref linkend='ex-toxml-co-apply' />) to
+    generate the XML configuration file for the Jetty server.  The XML
+    representation produced from <xref linkend='ex-toxml-co-servlets'
+    /> by <function>toXML</function> is shown in <xref
+    linkend='ex-toxml-result' />.</para>
+
+    <para>Note that <xref linkend='ex-toxml' /> uses the <function
+    linkend='builtin-toFile'>toFile</function> built-in to write the
+    builder and the stylesheet “inline” in the Nix expression.  The
+    path of the stylesheet is spliced into the builder at
+    <literal>xsltproc ${stylesheet}
+    <replaceable>...</replaceable></literal>.</para>
+
+    <example xml:id='ex-toxml'><title>Passing information to a builder
+    using <function>toXML</function></title>
+    
+<programlisting><![CDATA[
+{stdenv, fetchurl, libxslt, jira, uberwiki}:
+
+stdenv.mkDerivation (rec {
+  name = "web-server";
+
+  buildInputs = [libxslt];
+  
+  builder = builtins.toFile "builder.sh" "
+    source $stdenv/setup
+    mkdir $out
+    echo $servlets | xsltproc ${stylesheet} - > $out/server-conf.xml]]> <co xml:id='ex-toxml-co-apply' /> <![CDATA[
+  ";
+
+  stylesheet = builtins.toFile "stylesheet.xsl"]]> <co xml:id='ex-toxml-co-stylesheet' /> <![CDATA[
+   "<?xml version='1.0' encoding='UTF-8'?>
+    <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
+      <xsl:template match='/'>
+        <Configure>
+          <xsl:for-each select='/expr/list/attrs'>
+            <Call name='addWebApplication'>
+              <Arg><xsl:value-of select=\"attr[@name = 'path']/string/@value\" /></Arg>
+              <Arg><xsl:value-of select=\"attr[@name = 'war']/path/@value\" /></Arg>
+            </Call>
+          </xsl:for-each>
+        </Configure>
+      </xsl:template>
+    </xsl:stylesheet>
+  ";
+
+  servlets = builtins.toXML []]> <co xml:id='ex-toxml-co-servlets' /> <![CDATA[
+    { path = "/bugtracker"; war = jira + "/lib/atlassian-jira.war"; }
+    { path = "/wiki"; war = uberwiki + "/uberwiki.war"; }
+  ];
+})]]></programlisting>
+
+    </example>
+
+    <example xml:id='ex-toxml-result'><title>XML representation produced by
+    <function>toXML</function></title>
+    
+<programlisting><![CDATA[<?xml version='1.0' encoding='utf-8'?>
+<expr>
+  <list>
+    <attrs>
+      <attr name="path">
+        <string value="/bugtracker" />
+      </attr>
+      <attr name="war">
+        <path value="/nix/store/d1jh9pasa7k2...-jira/lib/atlassian-jira.war" />
+      </attr>
+    </attrs>
+    <attrs>
+      <attr name="path">
+        <string value="/wiki" />
+      </attr>
+      <attr name="war">
+        <path value="/nix/store/y6423b1yi4sx...-uberwiki/uberwiki.war" />
+      </attr>
+    </attrs>
+  </list>
+</expr>]]></programlisting>
+
+    </example>
+
+    </listitem>
+
+  </varlistentry>
+
+  
+</variablelist>
+
+
+</section>