212 lines
7 KiB
HTML
212 lines
7 KiB
HTML
|
<!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>© Colin Allen & Maneesh Dhagat <BR>
|
||
|
March 2007 </I>
|
||
|
</ADDRESS>
|
||
|
</BODY>
|