emacs.d/clones/colinallen.dnsalias.org/lp/node46.html

154 lines
5.1 KiB
HTML
Raw Normal View History

2022-08-02 12:34:59 +02:00
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
<!Originally converted to HTML using LaTeX2HTML 95 (Thu Jan 19 1995) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds >
<HEAD>
<TITLE> Ensuring Proper Termination</TITLE>
</HEAD>
<BODY>
<meta name="description" value=" Ensuring Proper Termination">
<meta name="keywords" value="lp">
<meta name="resource-type" value="document">
<meta name="distribution" value="global">
<P>
<BR> <HR>
<A HREF="node47.html"><IMG ALIGN=BOTTOM ALT="next" SRC="next_motif.gif"></A>
<A HREF="node41.html"><IMG ALIGN=BOTTOM ALT="up" SRC="up_motif.gif"></A>
<A HREF="node45.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="previous_motif.gif"></A> <BR>
<A HREF="lp.html"><B>Contents</B></A>
<B> Next:</B>
<A HREF="node47.html"> Abstraction</A>
<B>Up:</B>
<A HREF="node41.html"> Programming Techniques</A>
<B> Previous:</B>
<A HREF="node45.html"> Recursion on Numbers</A>
<BR> <HR> <P>
<H1> Ensuring Proper Termination</H1>
<P>
Often it happens that the Lisp programmer unknowingly
implements an infinite loop. This could happen in two different ways:
an infinite ``do'' loop, or an improper recursion. In the first case,
it may be that the programmer is using the general ``do'' construct and
has specified a test for termination that will never occur. This
problem can be avoided by using the more specific constructs ``dotimes'' or
``dolist'' (chapter 3). These constructs have a built-in test for
termination; ``dotimes'' iterates a specified number of times, and
``dolist'' iterates once for each element in a given list. Improper
recursion, however, is often more difficult to discover.
<BLOCKQUOTE>
<PRE><TT> <H4><b>Example 8:
<P>
The following definition wrongly implements the function to determine
<P>
the length of a list:
<P>
<tt> (defun length (lst)</tt>
<P>
<tt> (cond ((null lst) 0)</tt>
<P>
<tt> (t (+ 1 (length lst)))))</tt>
<P>
</b></h4></TT></PRE>
</BLOCKQUOTE>
The following notation illustrates why the above function does
not terminate:
<BLOCKQUOTE>
<PRE>(length '(a b c))
= (+ 1 (length '(a b c)))
= (+ 1 (+ 1 (length '(a b c))))
= (+ 1 (+ 1 (+ 1 (length '(a b c)))))
= (+ 1 (+ 1 (+ 1 (+ 1 (length '(a b c))))))
= (+ 1 (+ 1 (+ 1 (+ 1 (+ 1 (length '(a b c)))))))
= ...
= ...
</PRE>
</BLOCKQUOTE>
The list is passed-in unmodified in the recursive call. Such simple
mistakes are very common, and their frequency increases with longer and
more complicated programs. Compare this definition of ``length'' with
the one given in section 4.2.
<BLOCKQUOTE>
<PRE><TT> <H4><b>RULE OF THUMB 7:
<P>
To ensure proper termination do two things:
<P>
(1) make sure that you are changing at least one argument
<P>
in your recursive call;
<P>
(2) make sure that your test for termination looks at the
<P>
arguments that change in the recursive call.
<P>
</b></h4></TT></PRE>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE><TT> <H4><b>Example 9:
<P>
A function, ``exp,'' takes two positive, non-zero integers, x and y, and
<P>
raises x to the y power. Will the following recursive definition for
<P>
``exp'' terminate properly?
<P>
<tt> (defun exp (x y)</tt>
<P>
<tt> (cond ((= y 0) 1)</tt>
<P>
<tt> (t (* x (exp x (- y 1))))))</tt>
<P>
</b></h4></TT></PRE>
</BLOCKQUOTE>
Yes, the above definition is correct and will terminate properly
according to Rule of Thumb 7. We fulfill both requirements of the
rule:
<DL COMPACT><DT>(1)
<DD> We are changing at least one argument in the
recursive call, namely y, which is decremented
by one.
<DT>(2)
<DD> In our test for termination, <code>(= y 0)</code>, we are
using an argument that we change in the
recursive call, namely y.
<P>
</DL>
<div style="border: 1px solid red; background: #ffffdd; margin: 10px; text-align: center"><b>NOTE:</b> The example above again illustrates that you are allowed to redefine functions that are built into Lisp. Programmer beware!!</div>
<BLOCKQUOTE>
<PRE><TT> <H4><b>RULE OF THUMB 8:
<P>
<b>Two simple cases may occur when changing an argument in a
<P>
<b>recursive call:
<P>
<b>(1) if you are using ``rest'' to change an argument which is
<P>
<b>a list, use ``null'' in the test for termination;
<P>
<b>(2) if you are decreasing an argument which is a number,
<P>
<b>compare it with 0 in the test for termination.
<P>
</TT></PRE>
</BLOCKQUOTE></H4></b></H4></b></b></b></b></b></b></H4></b></H4></b></b></b></b></b></b></b><BR> <HR>
<A HREF="node47.html"><IMG ALIGN=BOTTOM ALT="next" SRC="next_motif.gif"></A>
<A HREF="node41.html"><IMG ALIGN=BOTTOM ALT="up" SRC="up_motif.gif"></A>
<A HREF="node45.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="previous_motif.gif"></A> <BR>
<A HREF="lp.html"><B>Contents</B></A>
<B> Next:</B>
<A HREF="node47.html"> Abstraction</A>
<B>Up:</B>
<A HREF="node41.html"> Programming Techniques</A>
<B> Previous:</B>
<A HREF="node45.html"> Recursion on Numbers</A>
<BR> <HR> <P>
<BR> <HR>
<P>
<ADDRESS>
<I>&#169; Colin Allen &amp; Maneesh Dhagat <BR>
March 2007 </I>
</ADDRESS>
</BODY>