web/html/backup/ar01.html
changeset 0 8083d21c0020
equal deleted inserted replaced
-1:000000000000 0:8083d21c0020
       
     1 <html>
       
     2 <head>
       
     3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
       
     4 <title>Functional Approach</title>
       
     5 <link rel="stylesheet" href="/support/styles.css" type="text/css">
       
     6 <meta id="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide">
       
     7 <link rel="up" href="index.html" title="Mercurial: The Definitive Guide">
       
     8 <link rel="prev" href="managing-releases-and-branchy-development.html" title="Chapter 8. Managing releases and branchy development">
       
     9 <link rel="next" href="handling-repository-events-with-hooks.html" title="Chapter 10. Handling repository events with hooks"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/">
       
    10 <link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png">
       
    11 <script type="text/javascript" src="/support/jquery-min.js"></script>
       
    12 <script type="text/javascript" src="/support/form.js"></script>
       
    13 <script type="text/javascript" src="/support/hsbook.js"></script></head>
       
    14 </head>
       
    15 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
       
    16 <div class="navheader">
       
    17 <table width="100%" summary="Navigation header">
       
    18 <tr><th colspan="3" align="center">Functional Approach</th></tr>
       
    19 <tr>
       
    20 <td width="20%" align="left">
       
    21 <a accesskey="p" href="index.html">Prev</a> </td>
       
    22 <th width="60%" align="center"> </th>
       
    23 <td width="20%" align="right"> </td>
       
    24 </tr>
       
    25 </table>
       
    26 <hr>
       
    27 </div>
       
    28 <div class="article" title="Functional Approach">
       
    29 <div class="titlepage">
       
    30 <div><div><h2 class="title">
       
    31 <a name="id2496165"></a>Functional Approach</h2></div></div>
       
    32 <hr>
       
    33 </div>
       
    34 <div class="toc">
       
    35 <p><b>Table of Contents</b></p>
       
    36 <dl>
       
    37 <dt><span class="section"><a href="ar01.html#default-arguments">1. Default Arguments</a></span></dt>
       
    38 <dt><span class="section"><a href="ar01.html#keyword-arguments">2. Keyword Arguments</a></span></dt>
       
    39 <dt><span class="section"><a href="ar01.html#parameter-packing-and-unpacking">3. Parameter Packing and Unpacking</a></span></dt>
       
    40 <dt><span class="section"><a href="ar01.html#nested-functions-and-scopes">4. Nested Functions and Scopes</a></span></dt>
       
    41 <dt><span class="section"><a href="ar01.html#map-reduce-and-filter-functions">5. map, reduce and filter functions</a></span></dt>
       
    42 <dd><dl><dt><span class="section"><a href="ar01.html#list-comprehensions">5.1. List Comprehensions</a></span></dt></dl></dd>
       
    43 </dl>
       
    44 </div>
       
    45 <p id="x_74b"><a name="x_74b"></a>
       
    46     <span class="emphasis"><em>Functions</em></span> allow us to enclose a set of statements and call the function again and again instead of repeating the group of statements everytime. Functions also allow us to isolate a piece of code from all the other code and provides the convenience of not polluting the global variables.
       
    47   </p>
       
    48 <p id="x_74c"><a name="x_74c"></a>
       
    49     <span class="emphasis"><em>Function</em></span> in python is defined with the keyword 
       
    50     <span class="strong"><strong>def</strong></span> followed by the name of the function, in turn followed by a pair of parenthesis which encloses the list of parameters to the function. The definition line ends with a ':'. The definition line is followed by the body of the function intended by one block. The 
       
    51     <span class="emphasis"><em>Function</em></span> must return a value:
       
    52   </p>
       
    53 <pre class="programlisting">def factorial(n):
       
    54   fact = 1
       
    55   for i in range(2, n):
       
    56     fact *= i
       
    57 
       
    58   return fact
       
    59 
       
    60 </pre>
       
    61 <p id="x_74d"><a name="x_74d"></a>The code snippet above defines a function with the name factorial, takes the number for which the factorial must be computed, computes the factorial and returns the value.</p>
       
    62 <p><a name="x_74e"></a>A 
       
    63     <span class="emphasis"><em>Function</em></span> once defined can be used or called anywhere else in the program. We call a fucntion with its name followed by a pair of parenthesis which encloses the arguments to the function.
       
    64   </p>
       
    65 <p><a name="x_74f"></a>The value that function returns can be assigned to a variable. Let's call the above function and store the factorial in a variable:</p>
       
    66 <pre class="programlisting">fact5 = factorial(5)
       
    67 
       
    68 </pre>
       
    69 <p><a name="x_750"></a>The value of fact5 will now be 120, which is the factorial of 5. Note that we passed 5 as the argument to the function.</p>
       
    70 <p><a name="x_751"></a>It may be necessary to document what the function does, for each of the function to help the person who reads our code to understand it better. In order to do this Python allows the first line of the function body to be a string. This string is called as 
       
    71     <span class="emphasis"><em>Documentation String</em></span> or 
       
    72     <span class="emphasis"><em>docstring</em></span>. 
       
    73     <span class="emphasis"><em>docstrings</em></span> prove to be very handy since there are number of tools which can pull out all the docstrings from Python functions and generate the documentation automatically from it. 
       
    74     <span class="emphasis"><em>docstrings</em></span> for functions can be written as follows:
       
    75   </p>
       
    76 <pre class="programlisting">def factorial(n):
       
    77   'Returns the factorial for the number n.'
       
    78   fact = 1
       
    79   for i in range(2, n):
       
    80     fact *= i
       
    81 
       
    82   return fact
       
    83 
       
    84 </pre>
       
    85 <p><a name="x_752"></a>An important point to note at this point is that, a function can return any Python value or a Python object, which also includes a 
       
    86     <span class="emphasis"><em>Tuple</em></span>. A 
       
    87     <span class="emphasis"><em>Tuple</em></span> is just a collection of values and those values themselves can be of any other valid Python datatypes, including 
       
    88     <span class="emphasis"><em>Lists</em></span>, 
       
    89     <span class="emphasis"><em>Tuples</em></span>, 
       
    90     <span class="emphasis"><em>Dictionaries</em></span> among other things. So effectively, if a function can return a tuple, it can return any number of values through a tuple
       
    91   </p>
       
    92 <p><a name="x_753"></a>Let us write a small function to swap two values:</p>
       
    93 <pre class="programlisting">def swap(a, b):
       
    94   return b, a
       
    95 
       
    96 c, d = swap(a, b)
       
    97 
       
    98 </pre>
       
    99 <p><a name="x_754"></a>Function scope --------------- The variables used inside the function are confined to the function's scope and doesn't pollute the variables of the same name outside the scope of the function. Also the arguments passed to the function are passed by-value if it is of basic Python data type:</p>
       
   100 <pre class="programlisting">def cant_change(n):
       
   101   n = 10
       
   102 
       
   103 n = 5
       
   104 cant_change(n)
       
   105 
       
   106 </pre>
       
   107 <p><a name="x_755"></a>Upon running this code, what do you think would have happened to value of n which was assigned 5 before the function call? If you have already tried out that snippet on the interpreter you already know that the value of n is not changed. This is true of any immutable types of Python like 
       
   108     <span class="emphasis"><em>Numbers</em></span>, 
       
   109     <span class="emphasis"><em>Strings</em></span> and 
       
   110     <span class="emphasis"><em>Tuples</em></span>. But when you pass mutable objects like 
       
   111     <span class="emphasis"><em>Lists</em></span> and 
       
   112     <span class="emphasis"><em>Dictionaries</em></span> the values are manipulated even outside the function:
       
   113   </p>
       
   114 <pre class="programlisting">&gt;&gt;&gt; def can_change(n):
       
   115 ...   n[1] = James
       
   116 ...
       
   117 
       
   118 &gt;&gt;&gt; name = ['Mr.', 'Steve', 'Gosling']
       
   119 &gt;&gt;&gt; can_change(name)
       
   120 &gt;&gt;&gt; name
       
   121 ['Mr.', 'James', 'Gosling']
       
   122 
       
   123 </pre>
       
   124 <p><a name="x_756"></a>If nothing is returned by the function explicitly, Python takes care to return None when the funnction is called.</p>
       
   125 <div class="section" title="1. Default Arguments">
       
   126 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   127 <a name="default-arguments"></a>1. Default Arguments</h2></div></div></div>
       
   128 <p><a name="x_757"></a>There may be situations where we need to allow the functions to take the arguments optionally. Python allows us to define function this way by providing a facility called 
       
   129       <span class="emphasis"><em>Default Arguments</em></span>. For example, we need to write a function that returns a list of fibonacci numbers. Since our function cannot generate an infinite list of fibonacci numbers, we need to specify the number of elements that the fibonacci sequence must contain. Suppose, additionally, we want to the function to return 10 numbers in the sequence if no option is specified we can define the function as follows:
       
   130     </p>
       
   131 <pre class="programlisting">def fib(n=10):
       
   132   fib_list = [0, 1]
       
   133   for i in range(n - 2):
       
   134     next = fib_list[-2] + fib_list[-1]
       
   135     fib_list.append(next)
       
   136   return fib_list
       
   137 
       
   138 </pre>
       
   139 <p><a name="x_758"></a>When we call this function, we can optionally specify the value for the parameter n, during the call as an argument. Calling with no argument and argument with n=5 returns the following fibonacci sequences:</p>
       
   140 <pre class="programlisting">fib()
       
   141 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
       
   142 fib(5)
       
   143 [0, 1, 1, 2, 3]
       
   144 
       
   145 </pre>
       
   146 </div>
       
   147 <div class="section" title="2. Keyword Arguments">
       
   148 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   149 <a name="keyword-arguments"></a>2. Keyword Arguments</h2></div></div></div>
       
   150 <p><a name="x_759"></a>When a function takes a large number of arguments, it may be difficult to remember the order of the parameters in the function definition or it may be necessary to pass values to only certain parameters since others take the default value. In either of these cases, Python provides the facility of passing arguments by specifying the name of the parameter as defined in the function definition. This is known as 
       
   151       <span class="emphasis"><em>Keyword Arguments</em></span>.
       
   152     </p>
       
   153 <p><a name="x_75a"></a>In a function call, 
       
   154       <span class="emphasis"><em>Keyword arguments</em></span> can be used for each argument, in the following fashion:
       
   155     </p>
       
   156 <pre class="programlisting">argument_name=argument_value
       
   157 Also denoted as: keyword=argument
       
   158 
       
   159 def wish(name='World', greetings='Hello'):
       
   160   print "%s, %s!" % (greetings, name)
       
   161 
       
   162 </pre>
       
   163 <p><a name="x_75b"></a>This function can be called in one of the following ways. It is important to note that no restriction is imposed in the order in which 
       
   164       <span class="emphasis"><em>Keyword arguments</em></span> can be specified. Also note, that we have combined 
       
   165       <span class="emphasis"><em>Keyword arguments</em></span> with 
       
   166       <span class="emphasis"><em>Default arguments</em></span> in this example, however it is not necessary:
       
   167     </p>
       
   168 <pre class="programlisting">wish(name='Guido', greetings='Hey')
       
   169 wish(greetings='Hey', name='Guido')
       
   170 
       
   171 </pre>
       
   172 <p><a name="x_75c"></a>Calling functions by specifying arguments in the order of parameters specified in the function definition is called as 
       
   173       <span class="emphasis"><em>Positional arguments</em></span>, as opposed to 
       
   174       <span class="emphasis"><em>Keyword arguments</em></span>. It is possible to use both 
       
   175       <span class="emphasis"><em>Positional arguments</em></span> and 
       
   176       <span class="emphasis"><em>Keyword arguments</em></span> in a single function call. But Python doesn't allow us to bungle up both of them. The arguments to the function, in the call, must always start with 
       
   177       <span class="emphasis"><em>Positional arguments</em></span> which is in turn followed by 
       
   178       <span class="emphasis"><em>Keyword arguments</em></span>:
       
   179     </p>
       
   180 <pre class="programlisting">def my_func(x, y, z, u, v, w):
       
   181   # initialize variables.
       
   182   ...
       
   183   # do some stuff 
       
   184   ...
       
   185   # return the value
       
   186 
       
   187 </pre>
       
   188 <p><a name="x_75d"></a>It is valid to call the above functions in the following ways:</p>
       
   189 <pre class="programlisting">my_func(10, 20, 30, u=1.0, v=2.0, w=3.0)
       
   190 my_func(10, 20, 30, 1.0, 2.0, w=3.0)
       
   191 my_func(10, 20, z=30, u=1.0, v=2.0, w=3.0)
       
   192 my_func(x=10, y=20, z=30, u=1.0, v=2.0, w=3.0)
       
   193 
       
   194 </pre>
       
   195 <p><a name="x_75e"></a>Following lists some of the invalid calls:</p>
       
   196 <pre class="programlisting">my_func(10, 20, z=30, 1.0, 2.0, 3.0)
       
   197 my_func(x=10, 20, z=30, 1.0, 2.0, 3.0)
       
   198 my_func(x=10, y=20, z=30, u=1.0, v=2.0, 3.0)
       
   199 
       
   200 </pre>
       
   201 </div>
       
   202 <div class="section" title="3. Parameter Packing and Unpacking">
       
   203 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   204 <a name="parameter-packing-and-unpacking"></a>3. Parameter Packing and Unpacking</h2></div></div></div>
       
   205 <p><a name="x_75f"></a>The positional arguments passed to a function can be collected in a tuple parameter and keyword arguments can be collected in a dictionary. Since keyword arguments must always be the last set of arguments passed to a function, the keyword dictionary parameter must be the last parameter. The function definition must include a list explicit parameters, followed by tuple paramter collecting parameter, whose name is preceded by a *****, for collecting positional parameters, in turn followed by the dictionary collecting parameter, whose name is preceded by a ****** :</p>
       
   206 <pre class="programlisting">def print_report(title, *args, **name):
       
   207   """Structure of *args*
       
   208   (age, email-id)
       
   209   Structure of *name*
       
   210   {
       
   211       'first': First Name
       
   212       'middle': Middle Name
       
   213       'last': Last Name
       
   214   }
       
   215   """
       
   216 
       
   217   print "Title: %s" % (title)
       
   218   print "Full name: %(first)s %(middle)s %(last)s" % name
       
   219   print "Age: %d\nEmail-ID: %s" % args
       
   220 
       
   221 </pre>
       
   222 <p><a name="x_760"></a>The above function can be called as. Note, the order of keyword parameters can be interchanged:</p>
       
   223 <pre class="programlisting">&gt;&gt;&gt; print_report('Employee Report', 29, 'johny@example.com', first='Johny',
       
   224                  last='Charles', middle='Douglas')
       
   225 Title: Employee Report
       
   226 Full name: Johny Douglas Charles
       
   227 Age: 29
       
   228 Email-ID: johny@example.com
       
   229 
       
   230 </pre>
       
   231 <p><a name="x_761"></a>The reverse of this can also be achieved by using a very identical syntax while calling the function. A tuple or a dictionary can be passed as arguments in place of a list of *Positional arguments* or *Keyword arguments* respectively using ***** or ****** :</p>
       
   232 <pre class="programlisting">def print_report(title, age, email, first, middle, last):
       
   233   print "Title: %s" % (title)
       
   234   print "Full name: %s %s %s" % (first, middle, last)
       
   235   print "Age: %d\nEmail-ID: %s" % (age, email)
       
   236 
       
   237 &gt;&gt;&gt; args = (29, 'johny@example.com')
       
   238 &gt;&gt;&gt; name = {
       
   239         'first': 'Johny',
       
   240         'middle': 'Charles',
       
   241         'last': 'Douglas'
       
   242         }
       
   243 &gt;&gt;&gt; print_report('Employee Report', *args, **name)
       
   244 Title: Employee Report
       
   245 Full name: Johny Charles Douglas
       
   246 Age: 29
       
   247 Email-ID: johny@example.com
       
   248 
       
   249 </pre>
       
   250 </div>
       
   251 <div class="section" title="4. Nested Functions and Scopes">
       
   252 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   253 <a name="nested-functions-and-scopes"></a>4. Nested Functions and Scopes</h2></div></div></div>
       
   254 <p><a name="x_762"></a>Python allows nesting one function inside another. This style of programming turns out to be extremely flexible and powerful features when we use 
       
   255       <span class="emphasis"><em>Python decorators</em></span>. We will not talk about decorators is beyond the scope of this course. If you are interested in knowing more about 
       
   256       <span class="emphasis"><em>decorator programming</em></span> in Python you are suggested to read:
       
   257     </p>
       
   258 <div class="literallayout"><p><br>
       
   259       <a class="ulink" href="http://avinashv.net/2008/04/python-decorators-syntactic-sugar" target="_top">http://avinashv.net/2008/04/python-decorators-syntactic-sugar</a>/<br>
       
   260       <a class="ulink" href="http://personalpages.tds.net" target="_top">http://personalpages.tds.net</a>/~kent37/kk/00001.html<br>
       
   261     </p></div>
       
   262 <p><a name="x_763"></a>However, the following is an example for nested functions in Python:</p>
       
   263 <pre class="programlisting">def outer():
       
   264   print "Outer..."
       
   265   def inner():
       
   266     print "Inner..."
       
   267   print "Outer..."
       
   268   inner()
       
   269 
       
   270 &gt;&gt;&gt; outer()
       
   271 
       
   272 </pre>
       
   273 </div>
       
   274 <div class="section" title="5. map, reduce and filter functions">
       
   275 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   276 <a name="map-reduce-and-filter-functions"></a>5. map, reduce and filter functions</h2></div></div></div>
       
   277 <p><a name="x_764"></a>Python provides several built-in functions for convenience. The 
       
   278       <span class="strong"><strong>map()</strong></span>, 
       
   279       <span class="strong"><strong>reduce()</strong></span> and 
       
   280       <span class="strong"><strong>filter()</strong></span> functions prove to be very useful with sequences like 
       
   281       <span class="emphasis"><em>Lists</em></span>.
       
   282     </p>
       
   283 <p><a name="x_765"></a>The 
       
   284       <span class="strong"><strong>map</strong></span> (
       
   285       <span class="emphasis"><em>function</em></span>, 
       
   286       <span class="emphasis"><em>sequence</em></span>) function takes two arguments: 
       
   287       <span class="emphasis"><em>function</em></span> and a 
       
   288       <span class="emphasis"><em>sequence</em></span> argument. The 
       
   289       <span class="emphasis"><em>function</em></span> argument must be the name of the function which in turn takes a single argument, the individual element of the 
       
   290       <span class="emphasis"><em>sequence</em></span>. The 
       
   291       <span class="strong"><strong>map</strong></span> function calls 
       
   292       <span class="emphasis"><em>function(item)</em></span>, for each item in the sequence and returns a list of values, where each value is the value returned by each call to 
       
   293       <span class="emphasis"><em>function(item)</em></span>. 
       
   294       <span class="strong"><strong>map()</strong></span> function allows to pass more than one sequence. In this case, the first argument, 
       
   295       <span class="emphasis"><em>function</em></span> must take as many arguments as the number of sequences passed. This function is called with each corresponding element in the each of the sequences, or 
       
   296       <span class="strong"><strong>None</strong></span> if one of the sequence is exhausted:
       
   297     </p>
       
   298 <pre class="programlisting">def square(x):
       
   299   return x*x
       
   300 
       
   301 &gt;&gt;&gt; map(square, [1, 2, 3, 4])
       
   302 [1, 4, 9, 16]
       
   303 
       
   304 def mul(x, y):
       
   305   return x*y
       
   306 
       
   307 &gt;&gt;&gt; map(mul, [1, 2, 3, 4], [6, 7, 8, 9])
       
   308 
       
   309 </pre>
       
   310 <p><a name="x_766"></a>The 
       
   311       <span class="strong"><strong>filter</strong></span> (
       
   312       <span class="emphasis"><em>function</em></span>, 
       
   313       <span class="emphasis"><em>sequence</em></span>) function takes two arguments, similar to the 
       
   314       <span class="strong"><strong>map()</strong></span> function. The 
       
   315       <span class="strong"><strong>filter</strong></span> function calls 
       
   316       <span class="emphasis"><em>function(item)</em></span>, for each item in the sequence and returns all the elements in the sequence for which 
       
   317       <span class="emphasis"><em>function(item)</em></span> returned True:
       
   318     </p>
       
   319 <pre class="programlisting">def even(x):
       
   320   if x % 2:
       
   321     return True
       
   322   else:
       
   323     return False
       
   324 
       
   325 &gt;&gt;&gt; filter(even, range(1, 10))
       
   326 [1, 3, 5, 7, 9]
       
   327 
       
   328 </pre>
       
   329 <p><a name="x_767"></a>The 
       
   330       <span class="strong"><strong>reduce</strong></span> (
       
   331       <span class="emphasis"><em>function</em></span>, 
       
   332       <span class="emphasis"><em>sequence</em></span>) function takes two arguments, similar to 
       
   333       <span class="strong"><strong>map</strong></span> function, however multiple sequences are not allowed. The 
       
   334       <span class="strong"><strong>reduce</strong></span> function calls 
       
   335       <span class="emphasis"><em>function</em></span> with first two consecutive elements in the sequence, obtains the result, calls 
       
   336       <span class="emphasis"><em>function</em></span> with the result and the subsequent element in the sequence and so on until the end of the list and returns the final result:
       
   337     </p>
       
   338 <pre class="programlisting">def mul(x, y):
       
   339   return x*y
       
   340 
       
   341 &gt;&gt;&gt; reduce(mul, [1, 2, 3, 4])
       
   342 24
       
   343 
       
   344 </pre>
       
   345 <div class="section" title="5.1. List Comprehensions">
       
   346 <div class="titlepage"><div><div><h3 class="title">
       
   347 <a name="list-comprehensions"></a>5.1. List Comprehensions</h3></div></div></div>
       
   348 <p><a name="x_768"></a>List Comprehension is a convenvience utility provided by Python. It is a syntatic sugar to create 
       
   349         <span class="emphasis"><em>Lists</em></span>. Using 
       
   350         <span class="emphasis"><em>List Comprehensions</em></span> one can create 
       
   351         <span class="emphasis"><em>Lists</em></span> from other type of sequential data structures or other 
       
   352         <span class="emphasis"><em>Lists</em></span> itself. The syntax of 
       
   353         <span class="emphasis"><em>List Comprehensions</em></span> consists of a square brackets to indicate the result is a 
       
   354         <span class="emphasis"><em>List</em></span> within which we include at least one 
       
   355         <span class="strong"><strong>for</strong></span> clause and multiple 
       
   356         <span class="strong"><strong>if</strong></span> clauses. It will be more clear with an example:
       
   357       </p>
       
   358 <pre class="programlisting">&gt;&gt;&gt; num = [1, 2, 3]
       
   359 &gt;&gt;&gt; sq = [x*x for x in num]
       
   360 &gt;&gt;&gt; sq
       
   361 [1, 4, 9]
       
   362 &gt;&gt;&gt; all_num = [1, 2, 3, 4, 5, 6, 7, 8, 9]
       
   363 &gt;&gt;&gt; even = [x for x in all_num if x%2 == 0]
       
   364 
       
   365 </pre>
       
   366 <p><a name="x_769"></a>The syntax used here is very clear from the way it is written. It can be translated into english as, "for each element x in the list all_num, if remainder of x divided by 2 is 0, add x to the list."</p>
       
   367 </div>
       
   368 </div>
       
   369 </div>
       
   370 <div class="navfooter">
       
   371 <hr>
       
   372 <table width="100%" summary="Navigation footer">
       
   373 <tr>
       
   374 <td width="40%" align="left">
       
   375 <a accesskey="p" href="index.html">Prev</a> </td>
       
   376 <td width="20%" align="center"> </td>
       
   377 <td width="40%" align="right"> </td>
       
   378 </tr>
       
   379 <tr>
       
   380 <td width="40%" align="left" valign="top">Chapter 1.  </td>
       
   381 <td width="20%" align="center"> </td>
       
   382 <td width="40%" align="right" valign="top"> </td>
       
   383 </tr>
       
   384 </table>
       
   385 </div>
       
   386 </body>
       
   387 </html>