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

212 lines
7 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> Abstraction</TITLE>
</HEAD>
<BODY>
<meta name="description" value=" Abstraction">
<meta name="keywords" value="lp">
<meta name="resource-type" value="document">
<meta name="distribution" value="global">
<P>
<BR> <HR>
<A HREF="node48.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="node46.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="node48.html"> Summary of Rules</A>
<B>Up:</B>
<A HREF="node41.html"> Programming Techniques</A>
<B> Previous:</B>
<A HREF="node46.html"> Ensuring Proper Termination</A>
<BR> <HR> <P>
<H1> Abstraction</H1>
<P>
As a program becomes larger, it becomes increasingly difficult to
understand. When all of the details of the program are considered at
once, they may easily exceed the intellectual grasp of one person. To
increase the readability of the program, it is useful to abstract away
or ``hide'' unnecessary details. There are two areas in which
abstraction may be used: one may hide the details of the data one is
working with by using abstract data structures and associated
routines (chapter 5); or one may hide fragments of the program to
improve clarity. The latter is explored in this section. Hiding
fragments of the program increases clarity and often also results in
shorter programs.
<BLOCKQUOTE>
<PRE><TT> <H4><b>RULE OF THUMB 9:
<P>
Use ``let'' to reduce the number of function calls.
<P>
</b></h4></TT></PRE>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE><TT> <H4><b>Example 10:
<P>
Write a function called ``cube-list,'' which takes a list of numbers and
<P>
returns the same list with each element replaced with its cube. Thus,
<P>
<tt> (cube-list '(5 3 -15))</tt> should return <tt> (125 9 -3375)</tt>.
<P>
</b></h4></TT></PRE>
</BLOCKQUOTE>
By now, with the techniques presented above, the reader should be able
to see that the following is a possible solution:
<BLOCKQUOTE>
<PRE> (defun cube-list (lst)
(cond ((null lst) nil)
(t (cons (* (first lst)
(first lst)
(first lst))
(cube-list (rest lst))))))
</PRE>
</BLOCKQUOTE>
But note that to compute the cube of each element we must extract it
three times from the list using ``first.'' Using Rule of Thumb 9, we
can reduce this to only one use of ``first'' for each element. This
may be done as follows:
<BLOCKQUOTE>
<PRE> (defun cube-list (lst)
(cond ((null lst) nil)
(t (let ((elt (first lst)))
(cons (* elt elt elt)
(cube-list (rest lst)))))))
</PRE>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE><TT> <H4><b>RULE OF THUMB 10:
<P>
Encapsulate program fragments into new functions to
<P>
improve clarity.
<P>
</b></h4></TT></PRE>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE><TT> <H4><b>Example 11:
<P>
Write a function called ``cube,'' which takes a number and returns its
<P>
cube. Use ``cube'' to rewrite ``cube-list.''
<P>
</b></h4></TT></PRE>
</BLOCKQUOTE>
``cube'' is defined simply as follows:
<BLOCKQUOTE>
<PRE> (defun cube (elt)
(* elt elt elt))
</PRE>
</BLOCKQUOTE>
Now we can use ``cube'' to rewrite ``cube-list'':
<BLOCKQUOTE>
<PRE> (defun cube-list (lst)
(cond ((null lst) nil)
(t (cons (cube (first lst))
(cube-list (rest lst))))))
</PRE>
</BLOCKQUOTE>
These last two definitions are much easier to read and understand, and
they do not waste any function calls. Furthermore, cube is a useful tool that may be used in other function definitions.
<BLOCKQUOTE>
<PRE><TT> <H4><b>RULE OF THUMB 11:
<P>
Encapsulate repeated program fragments into new
<P>
functions to reduce program size.
<P>
</b></h4></TT></PRE>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE><TT> <H4><b>Example 12:
<P>
Suppose a list of two numbers represents a point in euclidean space.
<P>
Write a function called ``get-side,'' which takes three points, a, b, and
<P>
c, and a key, k. The three points represent the vertices of a triangle.
<P>
The function returns a value as follows:
<P>
if k = 1, returns length of side a-b;
<P>
if k = 2, returns length of side b-c;
<P>
if k = 3, returns length of side c-a;
<P>
else, returns 0.
<P>
</b></h4></TT></PRE>
</BLOCKQUOTE>
One possible solution is the following:
<BLOCKQUOTE>
<PRE> (defun get-side (a b c k)
(cond ((= k 1)
(sqrt (+ (exp (- (first a) (first b)) 2)
(exp (- (second a) (second b)) 2))))
((= k 2)
(sqrt (+ (exp (- (first b) (first c)) 2)
(exp (- (second b) (second c)) 2))))
((= k 3)
(sqrt (+ (exp (- (first c) (first a)) 2)
(exp (- (second c) (second a)) 2))))
(t 0)))
</PRE>
</BLOCKQUOTE>
Note that we are performing almost the same computation in the first
three cases of the ``cond'' clause; specifically, it is to calculate
the distance between two points.
<BLOCKQUOTE>
<PRE><TT> <H4><b>Example 13:
<P>
Write a function called ``distance,'' which takes two points (represented
<P>
as two-number lists), and returns the euclidean distance between them.
<P>
Use ``distance'' to rewrite ``get-side.''
<P>
</b></h4></TT></PRE>
</BLOCKQUOTE>
The function ``distance'' can be implemented simply as follows:
<BLOCKQUOTE>
<PRE> (defun distance (pt1 pt2)
(sqrt (+ (exp (- (first pt1) (first pt2)) 2)
(exp (- (second pt1) (second pt2)) 2))))
</PRE>
</BLOCKQUOTE>
Now we can rewrite ``get-side'' as follows:
<BLOCKQUOTE>
<PRE> (defun get-side (a b c k)
(cond ((= k 1) (distance a b))
((= k 2) (distance b c))
((= k 3) (distance c a))
(t 0)))
</PRE>
</BLOCKQUOTE>
Thus, using Rule of Thumb 11, we have reduced the size of the program
significantly, making it easier to understand.
<P>
The concept of abstraction is not unique to Lisp. It is also used in
other high-level programming languages such as C, Pascal, or FORTRAN.
<P>
</H4></b></b></H4></b></H4></b></b></b></H4></b></H4></b></b></b></H4></b></H4></b><BR> <HR>
<A HREF="node48.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="node46.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="node48.html"> Summary of Rules</A>
<B>Up:</B>
<A HREF="node41.html"> Programming Techniques</A>
<B> Previous:</B>
<A HREF="node46.html"> Ensuring Proper Termination</A>
<BR> <HR> <P>
<BR> <HR>
<P>
<ADDRESS>
<I>&#169; Colin Allen &amp; Maneesh Dhagat <BR>
March 2007 </I>
</ADDRESS>
</BODY>