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>
 |