102 lines
3.5 KiB
XML
102 lines
3.5 KiB
XML
|
<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-module-abstractions">
|
|||
|
<title>Abstractions</title>
|
|||
|
|
|||
|
<para>
|
|||
|
If you find yourself repeating yourself over and over, it’s time to
|
|||
|
abstract. Take, for instance, this Apache HTTP Server configuration:
|
|||
|
<programlisting>
|
|||
|
{
|
|||
|
<xref linkend="opt-services.httpd.virtualHosts"/> =
|
|||
|
{ "blog.example.org" = {
|
|||
|
documentRoot = "/webroot/blog.example.org";
|
|||
|
adminAddr = "alice@example.org";
|
|||
|
forceSSL = true;
|
|||
|
enableACME = true;
|
|||
|
enablePHP = true;
|
|||
|
};
|
|||
|
"wiki.example.org" = {
|
|||
|
documentRoot = "/webroot/wiki.example.org";
|
|||
|
adminAddr = "alice@example.org";
|
|||
|
forceSSL = true;
|
|||
|
enableACME = true;
|
|||
|
enablePHP = true;
|
|||
|
};
|
|||
|
};
|
|||
|
}
|
|||
|
</programlisting>
|
|||
|
It defines two virtual hosts with nearly identical configuration; the only
|
|||
|
difference is the document root directories. To prevent this
|
|||
|
duplication, we can use a <literal>let</literal>:
|
|||
|
<programlisting>
|
|||
|
let
|
|||
|
commonConfig =
|
|||
|
{ adminAddr = "alice@example.org";
|
|||
|
forceSSL = true;
|
|||
|
enableACME = true;
|
|||
|
};
|
|||
|
in
|
|||
|
{
|
|||
|
<xref linkend="opt-services.httpd.virtualHosts"/> =
|
|||
|
{ "blog.example.org" = (commonConfig // { documentRoot = "/webroot/blog.example.org"; });
|
|||
|
"wiki.example.org" = (commonConfig // { documentRoot = "/webroot/wiki.example.com"; });
|
|||
|
};
|
|||
|
}
|
|||
|
</programlisting>
|
|||
|
The <literal>let commonConfig = <replaceable>...</replaceable></literal>
|
|||
|
defines a variable named <literal>commonConfig</literal>. The
|
|||
|
<literal>//</literal> operator merges two attribute sets, so the
|
|||
|
configuration of the second virtual host is the set
|
|||
|
<literal>commonConfig</literal> extended with the document root option.
|
|||
|
</para>
|
|||
|
|
|||
|
<para>
|
|||
|
You can write a <literal>let</literal> wherever an expression is allowed.
|
|||
|
Thus, you also could have written:
|
|||
|
<programlisting>
|
|||
|
{
|
|||
|
<xref linkend="opt-services.httpd.virtualHosts"/> =
|
|||
|
let commonConfig = <replaceable>...</replaceable>; in
|
|||
|
{ "blog.example.org" = (commonConfig // { <replaceable>...</replaceable> })
|
|||
|
"wiki.example.org" = (commonConfig // { <replaceable>...</replaceable> })
|
|||
|
};
|
|||
|
}
|
|||
|
</programlisting>
|
|||
|
but not <literal>{ let commonConfig = <replaceable>...</replaceable>; in
|
|||
|
<replaceable>...</replaceable>; }</literal> since attributes (as opposed to
|
|||
|
attribute values) are not expressions.
|
|||
|
</para>
|
|||
|
|
|||
|
<para>
|
|||
|
<emphasis>Functions</emphasis> provide another method of abstraction. For
|
|||
|
instance, suppose that we want to generate lots of different virtual hosts,
|
|||
|
all with identical configuration except for the document root. This can be done
|
|||
|
as follows:
|
|||
|
<programlisting>
|
|||
|
{
|
|||
|
<xref linkend="opt-services.httpd.virtualHosts"/> =
|
|||
|
let
|
|||
|
makeVirtualHost = webroot:
|
|||
|
{ documentRoot = webroot;
|
|||
|
adminAddr = "alice@example.org";
|
|||
|
forceSSL = true;
|
|||
|
enableACME = true;
|
|||
|
};
|
|||
|
in
|
|||
|
{ "example.org" = (makeVirtualHost "/webroot/example.org");
|
|||
|
"example.com" = (makeVirtualHost "/webroot/example.com");
|
|||
|
"example.gov" = (makeVirtualHost "/webroot/example.gov");
|
|||
|
"example.nl" = (makeVirtualHost "/webroot/example.nl");
|
|||
|
};
|
|||
|
}
|
|||
|
</programlisting>
|
|||
|
Here, <varname>makeVirtualHost</varname> is a function that takes a single
|
|||
|
argument <literal>webroot</literal> and returns the configuration for a virtual
|
|||
|
host. That function is then called for several names to produce the list of
|
|||
|
virtual host configurations.
|
|||
|
</para>
|
|||
|
</section>
|