Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: twcamper/sicp-kindle
base: master
...
head fork: jonathanpatt/sicp-kindle
compare: master
Checking mergeability… Don’t worry, you can still create the pull request.
  • 8 commits
  • 253 files changed
  • 0 commit comments
  • 2 contributors
Showing with 19,494 additions and 41,556 deletions.
  1. +8 −2 content/book-Z-C.css
  2. BIN  content/book-Z-G-D-11.gif
  3. BIN  content/book-Z-G-D-12.gif
  4. BIN  content/book-Z-G-D-13.gif
  5. BIN  content/book-Z-G-D-14.gif
  6. BIN  content/book-Z-G-D-15.gif
  7. BIN  content/book-Z-G-D-16.gif
  8. BIN  content/book-Z-G-D-17.gif
  9. BIN  content/book-Z-G-D-18.gif
  10. BIN  content/book-Z-G-D-19.gif
  11. BIN  content/book-Z-G-D-20.gif
  12. BIN  content/book-Z-G-D-3.gif
  13. BIN  content/book-Z-G-D-4.gif
  14. BIN  content/book-Z-G-D-6.gif
  15. BIN  content/book-Z-G-D-9.gif
  16. +38 −41 content/book-Z-H-1.html
  17. +780 −1,614 content/book-Z-H-10.html
  18. +630 −1,581 content/book-Z-H-11.html
  19. +602 −1,352 content/book-Z-H-12.html
  20. +69 −229 content/book-Z-H-13.html
  21. +395 −861 content/book-Z-H-14.html
  22. +1,139 −2,490 content/book-Z-H-15.html
  23. +766 −1,651 content/book-Z-H-16.html
  24. +421 −1,037 content/book-Z-H-17.html
  25. +575 −1,606 content/book-Z-H-18.html
  26. +53 −92 content/book-Z-H-19.html
  27. +59 −91 content/book-Z-H-2.html
  28. +433 −1,082 content/book-Z-H-20.html
  29. +412 −821 content/book-Z-H-21.html
  30. +1,265 −2,577 content/book-Z-H-22.html
  31. +421 −1,141 content/book-Z-H-23.html
  32. +1,055 −2,434 content/book-Z-H-24.html
  33. +68 −207 content/book-Z-H-25.html
  34. +880 −2,138 content/book-Z-H-26.html
  35. +344 −776 content/book-Z-H-27.html
  36. +645 −1,563 content/book-Z-H-28.html
  37. +1,082 −2,889 content/book-Z-H-29.html
  38. +12 −29 content/book-Z-H-3.html
  39. +32 −89 content/book-Z-H-30.html
  40. +618 −1,237 content/book-Z-H-31.html
  41. +589 −1,254 content/book-Z-H-32.html
  42. +303 −805 content/book-Z-H-33.html
  43. +593 −1,217 content/book-Z-H-34.html
  44. +1,150 −2,865 content/book-Z-H-35.html
  45. +348 −336 content/book-Z-H-36.html
  46. +33 −378 content/book-Z-H-37.html
  47. +3,151 −4,164 content/book-Z-H-38.html
  48. +295 −156 content/book-Z-H-4.html
  49. +46 −211 content/book-Z-H-5.html
  50. +32 −69 content/book-Z-H-6.html
  51. +35 −121 content/book-Z-H-7.html
  52. +47 −142 content/book-Z-H-8.html
  53. +70 −208 content/book-Z-H-9.html
  54. BIN  content/cc-by-nc.png
  55. BIN  content/ch1-Z-G-1.gif
  56. BIN  content/ch1-Z-G-10.gif
  57. BIN  content/ch1-Z-G-11.gif
  58. BIN  content/ch1-Z-G-12.gif
  59. BIN  content/ch1-Z-G-13.gif
  60. BIN  content/ch1-Z-G-14.gif
  61. BIN  content/ch1-Z-G-15.gif
  62. BIN  content/ch1-Z-G-16.gif
  63. BIN  content/ch1-Z-G-17.gif
  64. BIN  content/ch1-Z-G-18.gif
  65. BIN  content/ch1-Z-G-19.gif
  66. BIN  content/ch1-Z-G-2.gif
  67. BIN  content/ch1-Z-G-20.gif
  68. BIN  content/ch1-Z-G-21.gif
  69. BIN  content/ch1-Z-G-22.gif
  70. BIN  content/ch1-Z-G-23.gif
  71. BIN  content/ch1-Z-G-24.gif
  72. BIN  content/ch1-Z-G-25.gif
  73. BIN  content/ch1-Z-G-26.gif
  74. BIN  content/ch1-Z-G-27.gif
  75. BIN  content/ch1-Z-G-28.gif
  76. BIN  content/ch1-Z-G-29.gif
  77. BIN  content/ch1-Z-G-3.gif
  78. BIN  content/ch1-Z-G-30.gif
  79. BIN  content/ch1-Z-G-31.gif
  80. BIN  content/ch1-Z-G-32.gif
  81. BIN  content/ch1-Z-G-33.gif
  82. BIN  content/ch1-Z-G-34.gif
  83. BIN  content/ch1-Z-G-35.gif
  84. BIN  content/ch1-Z-G-36.gif
  85. BIN  content/ch1-Z-G-37.gif
  86. BIN  content/ch1-Z-G-38.gif
  87. BIN  content/ch1-Z-G-4.gif
  88. BIN  content/ch1-Z-G-5.gif
  89. BIN  content/ch1-Z-G-6.gif
  90. BIN  content/ch1-Z-G-7.gif
  91. BIN  content/ch1-Z-G-8.gif
  92. BIN  content/ch1-Z-G-9.gif
  93. BIN  content/ch2-Z-G-1.gif
  94. BIN  content/ch2-Z-G-10.gif
  95. BIN  content/ch2-Z-G-11.gif
  96. BIN  content/ch2-Z-G-12.gif
  97. BIN  content/ch2-Z-G-13.gif
  98. BIN  content/ch2-Z-G-14.gif
  99. BIN  content/ch2-Z-G-15.gif
  100. BIN  content/ch2-Z-G-16.gif
  101. BIN  content/ch2-Z-G-17.gif
  102. BIN  content/ch2-Z-G-18.gif
  103. BIN  content/ch2-Z-G-19.gif
  104. BIN  content/ch2-Z-G-2.gif
  105. BIN  content/ch2-Z-G-20.gif
  106. BIN  content/ch2-Z-G-21.gif
  107. BIN  content/ch2-Z-G-22.gif
  108. BIN  content/ch2-Z-G-23.gif
  109. BIN  content/ch2-Z-G-24.gif
  110. BIN  content/ch2-Z-G-25.gif
  111. BIN  content/ch2-Z-G-26.gif
  112. BIN  content/ch2-Z-G-27.gif
  113. BIN  content/ch2-Z-G-28.gif
  114. BIN  content/ch2-Z-G-29.gif
  115. BIN  content/ch2-Z-G-3.gif
  116. BIN  content/ch2-Z-G-30.gif
  117. BIN  content/ch2-Z-G-31.gif
  118. BIN  content/ch2-Z-G-32.gif
  119. BIN  content/ch2-Z-G-33.gif
  120. BIN  content/ch2-Z-G-34.gif
  121. BIN  content/ch2-Z-G-35.gif
  122. BIN  content/ch2-Z-G-36.gif
  123. BIN  content/ch2-Z-G-37.gif
  124. BIN  content/ch2-Z-G-38.gif
  125. BIN  content/ch2-Z-G-39.gif
  126. BIN  content/ch2-Z-G-4.gif
  127. BIN  content/ch2-Z-G-40.gif
  128. BIN  content/ch2-Z-G-41.gif
  129. BIN  content/ch2-Z-G-42.gif
  130. BIN  content/ch2-Z-G-43.gif
  131. BIN  content/ch2-Z-G-44.gif
  132. BIN  content/ch2-Z-G-45.gif
  133. BIN  content/ch2-Z-G-46.gif
  134. BIN  content/ch2-Z-G-47.gif
  135. BIN  content/ch2-Z-G-48.gif
  136. BIN  content/ch2-Z-G-49.gif
  137. BIN  content/ch2-Z-G-5.gif
  138. BIN  content/ch2-Z-G-50.gif
  139. BIN  content/ch2-Z-G-51.gif
  140. BIN  content/ch2-Z-G-52.gif
  141. BIN  content/ch2-Z-G-53.gif
  142. BIN  content/ch2-Z-G-54.gif
  143. BIN  content/ch2-Z-G-55.gif
  144. BIN  content/ch2-Z-G-56.gif
  145. BIN  content/ch2-Z-G-57.gif
  146. BIN  content/ch2-Z-G-58.gif
  147. BIN  content/ch2-Z-G-59.gif
  148. BIN  content/ch2-Z-G-6.gif
  149. BIN  content/ch2-Z-G-60.gif
  150. BIN  content/ch2-Z-G-61.gif
  151. BIN  content/ch2-Z-G-62.gif
  152. BIN  content/ch2-Z-G-63.gif
  153. BIN  content/ch2-Z-G-64.gif
  154. BIN  content/ch2-Z-G-65.gif
  155. BIN  content/ch2-Z-G-66.gif
  156. BIN  content/ch2-Z-G-67.gif
  157. BIN  content/ch2-Z-G-68.gif
  158. BIN  content/ch2-Z-G-69.gif
  159. BIN  content/ch2-Z-G-7.gif
  160. BIN  content/ch2-Z-G-70.gif
  161. BIN  content/ch2-Z-G-71.gif
  162. BIN  content/ch2-Z-G-72.gif
  163. BIN  content/ch2-Z-G-73.gif
  164. BIN  content/ch2-Z-G-74.gif
  165. BIN  content/ch2-Z-G-75.gif
  166. BIN  content/ch2-Z-G-76.gif
  167. BIN  content/ch2-Z-G-77.gif
  168. BIN  content/ch2-Z-G-78.gif
  169. BIN  content/ch2-Z-G-79.gif
  170. BIN  content/ch2-Z-G-8.gif
  171. BIN  content/ch2-Z-G-80.gif
  172. BIN  content/ch2-Z-G-81.gif
  173. BIN  content/ch2-Z-G-9.gif
  174. BIN  content/ch3-Z-G-1.gif
  175. BIN  content/ch3-Z-G-10.gif
  176. BIN  content/ch3-Z-G-11.gif
  177. BIN  content/ch3-Z-G-12.gif
  178. BIN  content/ch3-Z-G-13.gif
  179. BIN  content/ch3-Z-G-14.gif
  180. BIN  content/ch3-Z-G-15.gif
  181. BIN  content/ch3-Z-G-16.gif
  182. BIN  content/ch3-Z-G-17.gif
  183. BIN  content/ch3-Z-G-18.gif
  184. BIN  content/ch3-Z-G-19.gif
  185. BIN  content/ch3-Z-G-2.gif
  186. BIN  content/ch3-Z-G-20.gif
  187. BIN  content/ch3-Z-G-21.gif
  188. BIN  content/ch3-Z-G-22.gif
  189. BIN  content/ch3-Z-G-23.gif
  190. BIN  content/ch3-Z-G-24.gif
  191. BIN  content/ch3-Z-G-25.gif
  192. BIN  content/ch3-Z-G-26.gif
  193. BIN  content/ch3-Z-G-27.gif
  194. BIN  content/ch3-Z-G-28.gif
  195. BIN  content/ch3-Z-G-29.gif
  196. BIN  content/ch3-Z-G-3.gif
  197. BIN  content/ch3-Z-G-30.gif
  198. BIN  content/ch3-Z-G-31.gif
  199. BIN  content/ch3-Z-G-32.gif
  200. BIN  content/ch3-Z-G-33.gif
  201. BIN  content/ch3-Z-G-34.gif
  202. BIN  content/ch3-Z-G-35.gif
  203. BIN  content/ch3-Z-G-36.gif
  204. BIN  content/ch3-Z-G-37.gif
  205. BIN  content/ch3-Z-G-38.gif
  206. BIN  content/ch3-Z-G-39.gif
  207. BIN  content/ch3-Z-G-4.gif
  208. BIN  content/ch3-Z-G-40.gif
  209. BIN  content/ch3-Z-G-41.gif
  210. BIN  content/ch3-Z-G-42.gif
  211. BIN  content/ch3-Z-G-43.gif
  212. BIN  content/ch3-Z-G-44.gif
  213. BIN  content/ch3-Z-G-45.gif
  214. BIN  content/ch3-Z-G-46.gif
  215. BIN  content/ch3-Z-G-47.gif
  216. BIN  content/ch3-Z-G-48.gif
  217. BIN  content/ch3-Z-G-49.gif
  218. BIN  content/ch3-Z-G-5.gif
  219. BIN  content/ch3-Z-G-50.gif
  220. BIN  content/ch3-Z-G-51.gif
  221. BIN  content/ch3-Z-G-52.gif
  222. BIN  content/ch3-Z-G-53.gif
  223. BIN  content/ch3-Z-G-54.gif
  224. BIN  content/ch3-Z-G-55.gif
  225. BIN  content/ch3-Z-G-56.gif
  226. BIN  content/ch3-Z-G-57.gif
  227. BIN  content/ch3-Z-G-58.gif
  228. BIN  content/ch3-Z-G-59.gif
  229. BIN  content/ch3-Z-G-6.gif
  230. BIN  content/ch3-Z-G-60.gif
  231. BIN  content/ch3-Z-G-7.gif
  232. BIN  content/ch3-Z-G-8.gif
  233. BIN  content/ch3-Z-G-9.gif
  234. BIN  content/ch4-Z-G-1.gif
  235. BIN  content/ch4-Z-G-10.gif
  236. BIN  content/ch4-Z-G-2.gif
  237. BIN  content/ch4-Z-G-3.gif
  238. BIN  content/ch4-Z-G-4.gif
  239. BIN  content/ch4-Z-G-5.gif
  240. BIN  content/ch4-Z-G-6.gif
  241. BIN  content/ch4-Z-G-7.gif
  242. BIN  content/ch4-Z-G-8.gif
  243. BIN  content/ch4-Z-G-9.gif
  244. BIN  content/ch5-Z-G-1.gif
  245. BIN  content/ch5-Z-G-2.gif
  246. BIN  content/ch5-Z-G-3.gif
  247. BIN  content/ch5-Z-G-4.gif
  248. BIN  content/ch5-Z-G-5.gif
  249. BIN  content/ch5-Z-G-6.gif
  250. BIN  content/ch5-Z-G-7.gif
  251. BIN  content/ch5-Z-G-8.gif
  252. BIN  content/ch5-Z-G-9.gif
  253. BIN  sicp.mobi
View
10 content/book-Z-C.css
@@ -49,6 +49,7 @@ ol ol ol ol {
}
.attrib {
+ font-size: 75%;
font-style: normal;
}
.figure {
@@ -75,5 +76,10 @@ background-color: pink;
color: gray;
}
-p { text-indent: 0}
-p.indent { text-indent: 1em}
+p {
+ text-indent: 0;
+ margin: 0;
+}
+p + p {
+ text-indent: 1em;
+}
View
BIN  content/book-Z-G-D-11.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-12.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-13.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-14.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-15.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-16.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-17.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-18.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-19.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-20.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-3.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-4.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-6.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  content/book-Z-G-D-9.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
79 content/book-Z-H-1.html
@@ -1,69 +1,66 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html>
+<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Generated from TeX source by tex2page, v 4o,
(c) Dorai Sitaram, http://www.cs.rice.edu/~dorai/tex2page -->
<head>
- <meta name="generator" content="HTML Tidy for Linux (vers 7 December 2008), see www.w3.org" />
+ <meta name="generator" content="HTML Tidy for Linux (vers 7 December 2008), see www.w3.org" />
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
- <title>Structure and Interpretation of Computer Programs</title>
- <link href="book-Z-C.css" title="default" rel="stylesheet" type="text/css" />
- <meta name="robots" content="noindex,follow" />
+ <title>Structure and Interpretation of Computer Programs</title>
+ <link href="book-Z-C.css" title="default" rel="stylesheet" type="text/css" />
+ <meta name="robots" content="noindex,follow" />
</head>
<body>
- <mbp:pagebreak />
+ <mbp:pagebreak />
- <p><a name="titlepage" id="titlepage"></a>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
+ <p><a name="titlepage" id="titlepage"></a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
- <h1>Structure and Interpretation<br />
- of Computer Programs</h1>
+ <h1>Structure and Interpretation<br />
+ of Computer Programs</h1>
- <div align="left">
- second edition&nbsp;
- </div>
+ <div align="left">
+ second edition&nbsp;
+ </div>
- <p><br /></p>
+ <p><br /></p>
- <p><br /></p>
+ <p><br /></p>
- <p><br /></p>
+ <p><br /></p>
- <p><br /></p>
+ <p><br /></p>
- <div align="left">
- Harold Abelson and Gerald Jay Sussman<br />
- with Julie Sussman&nbsp;
- </div>
+ <div align="left">
+ Harold Abelson and Gerald Jay Sussman<br />
+ with Julie Sussman&nbsp;
+ </div>
- <div align="left">
- foreword by Alan J. Perlis&nbsp;
- </div>
+ <div align="left">
+ foreword by Alan J. Perlis&nbsp;
+ </div>
- <p><br /></p>
+ <p><br /></p>
- <p><br /></p>
+ <p><br /></p>
- <p><br /></p>
+ <p><br /></p>
- <p><br /></p>
+ <p><br /></p>
- <p><br /></p>
+ <p><br /></p>
- <p><br /></p>
+ <p><br /></p>
- <div align="left">
- The MIT Press<br />
- Cambridge, Massachusetts &nbsp;&nbsp;&nbsp; London, England
+ <div align="left">
+ The MIT Press<br />
+ Cambridge, Massachusetts &nbsp;&nbsp;&nbsp; London, England
- <p>McGraw-Hill Book Company<br />
- New York &nbsp;&nbsp;&nbsp; St. Louis &nbsp;&nbsp;&nbsp; San
- Francisco &nbsp;&nbsp;&nbsp; Montreal &nbsp;&nbsp;&nbsp;
- Toronto&nbsp;</p>
- </div>
-
-
+ <p>McGraw-Hill Book Company<br />
+ New York &nbsp;&nbsp;&nbsp; St. Louis &nbsp;&nbsp;&nbsp; San Francisco &nbsp;&nbsp;&nbsp; Montreal &nbsp;&nbsp;&nbsp; Toronto&nbsp;</p>
+ </div>
</body>
</html>
View
2,394 content/book-Z-H-10.html
780 additions, 1,614 deletions not shown
View
2,211 content/book-Z-H-11.html
630 additions, 1,581 deletions not shown
View
1,954 content/book-Z-H-12.html
602 additions, 1,352 deletions not shown
View
298 content/book-Z-H-13.html
@@ -1,240 +1,80 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html>
+<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Generated from TeX source by tex2page, v 4o,
(c) Dorai Sitaram, http://www.cs.rice.edu/~dorai/tex2page -->
<head>
- <meta name="generator" content="HTML Tidy for Linux (vers 7 December 2008), see www.w3.org" />
+ <meta name="generator" content="HTML Tidy for Linux (vers 7 December 2008), see www.w3.org" />
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
- <title>Structure and Interpretation of Computer Programs</title>
- <link href="book-Z-C.css" title="default" rel="stylesheet" type="text/css" />
- <meta name="robots" content="noindex,follow" />
+ <title>Structure and Interpretation of Computer Programs</title>
+ <link href="book-Z-C.css" title="default" rel="stylesheet" type="text/css" />
+ <meta name="robots" content="noindex,follow" />
</head>
<body>
- <mbp:pagebreak />
-
- <p><a name="%_chap_2"></a></p>
-
- <div class="chapterheading">
- <h3 class="chapter"><a href="book-Z-H-4.html#%_toc_%_chap_2">Chapter 2</a></h3>
- <h1>Building Abstractions with Data</h1>
- </div>
-
- <div align="right">
- <table width="60%">
- <tr>
- <td>
- <div><span class="epigraph">&quot;We now come to the decisive step of mathematical abstraction: we forget about what
- the symbols stand for. <tt>...</tt>[The mathematician] need not be idle; there are many operations which he may
- carry out with these symbols, without ever having to look at the things they stand for.&quot;</span></div>
-
- <div><span class="epigraph attrib"><a name="%_idx_1254"></a>Hermann Weyl, <em>The Mathematical Way of Thinking</em></span></div>
- </td>
- </tr>
- </table>
- </div>
-
- <p><a name="%_idx_1256"></a><a name="%_idx_1258"></a>We
- concentrated in chapter&nbsp;1 on computational processes and on
- the role of procedures in program design. We saw how to use
- primitive data (numbers) and primitive operations (arithmetic
- operations), how to combine procedures to form compound
- procedures through composition, conditionals, and the use of
- parameters, and how to abstract procedures by using
- <tt>define</tt>. We saw that a procedure can be regarded as a
- pattern for the local evolution of a process, and we classified,
- reasoned about, and performed simple algorithmic analyses of some
- common patterns for processes as embodied in procedures. We also
- saw that higher-order procedures enhance the power of our
- language by enabling us to manipulate, and thereby to reason in
- terms of, general methods of computation. This is much of the
- essence of programming.</p>
-
- <p>In this chapter we are going to look at more complex data. All
- the procedures in chapter&nbsp;1 operate on simple numerical
- data, and simple data are not sufficient for many of the problems
- we wish to address using computation. Programs are typically
- designed to model complex phenomena, and more often than not one
- must construct computational objects that have several parts in
- order to model real-world phenomena that have several aspects.
- Thus, whereas our focus in chapter&nbsp;1 was on building
- abstractions by combining procedures to form compound procedures,
- we turn in this chapter to another key aspect of any programming
- language: the means it provides for building abstractions by
- combining data objects to form <em>compound data</em>.</p>
-
- <p>Why do we want compound data in a programming language? For
- the same reasons that we want compound procedures: to elevate the
- conceptual level at which we can design our programs, to increase
- the modularity of our designs, and to enhance the expressive
- power of our language. Just as the ability to define procedures
- enables us to deal with processes at a higher conceptual level
- than that of the primitive operations of the language, the
- ability to construct compound data objects enables us to deal
- with data at a higher conceptual level than that of the primitive
- data objects of the language.</p>
-
- <p><a name="%_idx_1260"></a>Consider the task of designing a
- system to perform arithmetic with rational numbers. We could
- imagine an operation <tt>add-rat</tt> that takes two rational
- numbers and produces their sum. In terms of simple data, a
- rational number can be thought of as two integers: a numerator
- and a denominator. Thus, we could design a program in which each
- rational number would be represented by two integers (a numerator
- and a denominator) and where <tt>add-rat</tt> would be
- implemented by two procedures (one producing the numerator of the
- sum and one producing the denominator). But this would be
- awkward, because we would then need to explicitly keep track of
- which numerators corresponded to which denominators. In a system
- intended to perform many operations on many rational numbers,
- such bookkeeping details would clutter the programs
- substantially, to say nothing of what they would do to our minds.
- It would be much better if we could ``glue together'' a numerator
- and denominator to form a pair -- a <em>compound data object</em>
- -- that our programs could manipulate in a way that would be
- consistent with regarding a rational number as a single
- conceptual unit.</p>
-
- <p>The use of compound data also enables us to increase the
- modularity of our programs. If we can manipulate rational numbers
- directly as objects in their own right, then we can separate the
- part of our program that deals with rational numbers per se from
- the details of how rational numbers may be represented as pairs
- of integers. The general technique of isolating the parts of a
- program that deal with how data objects are represented from the
- parts of a program that deal with how data objects are used is a
- powerful design methodology called <a name="%_idx_1262"></a><em>data abstraction</em>. We will see how data
- abstraction makes programs much easier to design, maintain, and
- modify.</p>
-
- <p>The use of compound data leads to a real increase in the
- expressive power of our programming language. Consider the idea
- of forming a ``linear combination'' <em>a</em><em>x</em> +
- <em>b</em><em>y</em>. We might like to write a procedure that
- would accept <em>a</em>, <em>b</em>, <em>x</em>, and <em>y</em>
- as arguments and return the value of <em>a</em><em>x</em> +
- <em>b</em><em>y</em>. This presents no difficulty if the
- arguments are to be numbers, because we can readily define the
- procedure</p>
-
- <p>
- <tt>(define&nbsp;(linear-combination&nbsp;a&nbsp;b&nbsp;x&nbsp;y)&nbsp;<br />
-
- &nbsp;&nbsp;(+&nbsp;(*&nbsp;a&nbsp;x)&nbsp;(*&nbsp;b&nbsp;y)))<br />
- </tt></p>
-
- <p>But suppose we are not concerned only with numbers. Suppose we
- would like to express, in procedural terms, the idea that one can
- form linear combinations whenever addition and multiplication are
- defined -- for rational numbers, complex numbers, polynomials, or
- whatever. We could express this as a procedure of the form</p>
-
- <p>
- <tt>(define&nbsp;(linear-combination&nbsp;a&nbsp;b&nbsp;x&nbsp;y)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
-
- &nbsp;&nbsp;(add&nbsp;(mul&nbsp;a&nbsp;x)&nbsp;(mul&nbsp;b&nbsp;y)))&nbsp;<br />
- </tt></p>
-
- <p>where <tt>add</tt> and <tt>mul</tt> are not the primitive
- procedures <tt>+</tt> and <tt>*</tt> but rather more complex
- things that will perform the appropriate operations for whatever
- kinds of data we pass in as the arguments <tt>a</tt>, <tt>b</tt>,
- <tt>x</tt>, and <tt>y</tt>. The key point is that the only thing
- <tt>linear-combination</tt> should need to know about <tt>a</tt>,
- <tt>b</tt>, <tt>x</tt>, and <tt>y</tt> is that the procedures
- <tt>add</tt> and <tt>mul</tt> will perform the appropriate
- manipulations. From the perspective of the procedure
- <tt>linear-combination</tt>, it is irrelevant what <tt>a</tt>,
- <tt>b</tt>, <tt>x</tt>, and <tt>y</tt> are and even more
- irrelevant how they might happen to be represented in terms of
- more primitive data. This same example shows why it is important
- that our programming language provide the ability to manipulate
- compound objects directly: Without this, there is no way for a
- procedure such as <tt>linear-combination</tt> to pass its
- arguments along to <tt>add</tt> and <tt>mul</tt> without having
- to know their detailed structure.<a href="#footnote_Temp_131" name="call_footnote_Temp_131" id="call_footnote_Temp_131"><sup><small>1</small></sup></a> We begin
- this chapter by implementing the rational-number arithmetic
- system mentioned above. This will form the background for our
- discussion of compound data and data abstraction. As with
- compound procedures, the main issue to be addressed is that of
- abstraction as a technique for coping with complexity, and we
- will see how data abstraction enables us to erect suitable
- <a name="%_idx_1264"></a><em>abstraction barriers</em> between
- different parts of a program.</p>
-
- <p>We will see that the key to forming compound data is that a
- programming language should provide some kind of ``glue'' so that
- data objects can be combined to form more complex data objects.
- There are many possible kinds of glue. Indeed, we will discover
- how to form compound data using no special ``data'' operations at
- all, only procedures. This will further blur the distinction
- between ``procedure'' and ``data,'' which was already becoming
- tenuous toward the end of chapter&nbsp;1. We will also explore
- some conventional techniques for representing sequences and
- trees. One key idea in dealing with compound data is the notion
- of <a name="%_idx_1266"></a><em>closure</em> -- that the glue we
- use for combining data objects should allow us to combine not
- only primitive data objects, but compound data objects as well.
- Another key idea is that compound data objects can serve as
- <a name="%_idx_1268"></a><em>conventional interfaces</em> for
- combining program modules in mix-and-match ways. We illustrate
- some of these ideas by presenting a simple graphics language that
- exploits closure.</p>
-
- <p>We will then augment the representational power of our
- language by introducing <a name="%_idx_1270"></a><a name="%_idx_1272"></a><em>symbolic expressions</em> -- data whose
- elementary parts can be arbitrary symbols rather than only
- numbers. We explore various alternatives for representing sets of
- objects. We will find that, just as a given numerical function
- can be computed by many different computational processes, there
- are many ways in which a given data structure can be represented
- in terms of simpler objects, and the choice of representation can
- have significant impact on the time and space requirements of
- processes that manipulate the data. We will investigate these
- ideas in the context of symbolic differentiation, the
- representation of sets, and the encoding of information.</p>
-
- <p>Next we will take up the problem of working with data that may
- be represented differently by different parts of a program. This
- leads to the need to implement <a name="%_idx_1274"></a><a name="%_idx_1276"></a><em>generic operations</em>, which must handle
- many different types of data. Maintaining modularity in the
- presence of generic operations requires more powerful abstraction
- barriers than can be erected with simple data abstraction alone.
- In particular, we introduce <em>data-directed programming</em> as
- a technique that allows individual data representations to be
- designed in isolation and then combined <a name="%_idx_1278"></a><em>additively</em> (i.e., without
- modification). To illustrate the power of this approach to system
- design, we close the chapter by applying what we have learned to
- the implementation of a package for performing symbolic
- arithmetic on polynomials, in which the coefficients of the
- polynomials can be integers, rational numbers, complex numbers,
- and even other polynomials.</p>
-
- <div class="smallprint">
- <hr />
- </div>
-
- <div class="footnote">
- <p><a href="#call_footnote_Temp_131" name="footnote_Temp_131" id="footnote_Temp_131"><sup><small>1</small></sup></a> The
- ability to directly manipulate procedures provides an analogous
- increase in the expressive power of a programming language. For
- example, in section&nbsp;<a href="book-Z-H-12.html#%_sec_1.3.1">1.3.1</a> we introduced the
- <tt>sum</tt> procedure, which takes a procedure <tt>term</tt>
- as an argument and computes the sum of the values of
- <tt>term</tt> over some specified interval. In order to define
- <tt>sum</tt>, it is crucial that we be able to speak of a
- procedure such as <tt>term</tt> as an entity in its own right,
- without regard for how <tt>term</tt> might be expressed with
- more primitive operations. Indeed, if we did not have the
- notion of ``a procedure,'' it is doubtful that we would ever
- even think of the possibility of defining an operation such as
- <tt>sum</tt>. Moreover, insofar as performing the summation is
- concerned, the details of how <tt>term</tt> may be constructed
- from more primitive operations are irrelevant.</p>
- </div>
-
-
+ <mbp:pagebreak />
+
+ <p><a name="%_chap_2"></a></p>
+
+ <div class="chapterheading">
+ <h3 class="chapter"><a href="book-Z-H-4.html#%_toc_%_chap_2">Chapter 2</a></h3>
+
+ <h1>Building Abstractions with Data</h1>
+ </div>
+
+ <div align="center">
+ <table width="80%">
+ <tr>
+ <td>
+ <div>
+ <span class="epigraph">“We now come to the decisive step of mathematical abstraction: we forget about what the symbols stand for. <tt>…</tt>[The mathematician] need not be idle; there are many operations which he may carry out with these symbols, without ever having to look at the things they stand for.”</span>
+ </div>
+
+ <div>
+ <span class="epigraph attrib"><a name="%_idx_1254"></a>Hermann Weyl, <em>The Mathematical Way of Thinking</em></span>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <p><a name="%_idx_1256"></a><a name="%_idx_1258"></a>We concentrated in chapter&nbsp;1 on computational processes and on the role of procedures in program design. We saw how to use primitive data (numbers) and primitive operations (arithmetic operations), how to combine procedures to form compound procedures through composition, conditionals, and the use of parameters, and how to abstract procedures by using <tt>define</tt>. We saw that a procedure can be regarded as a pattern for the local evolution of a process, and we classified, reasoned about, and performed simple algorithmic analyses of some common patterns for processes as embodied in procedures. We also saw that higher-order procedures enhance the power of our language by enabling us to manipulate, and thereby to reason in terms of, general methods of computation. This is much of the essence of programming.</p>
+
+ <p>In this chapter we are going to look at more complex data. All the procedures in chapter&nbsp;1 operate on simple numerical data, and simple data are not sufficient for many of the problems we wish to address using computation. Programs are typically designed to model complex phenomena, and more often than not one must construct computational objects that have several parts in order to model real-world phenomena that have several aspects. Thus, whereas our focus in chapter&nbsp;1 was on building abstractions by combining procedures to form compound procedures, we turn in this chapter to another key aspect of any programming language: the means it provides for building abstractions by combining data objects to form <em>compound data</em>.</p>
+
+ <p>Why do we want compound data in a programming language? For the same reasons that we want compound procedures: to elevate the conceptual level at which we can design our programs, to increase the modularity of our designs, and to enhance the expressive power of our language. Just as the ability to define procedures enables us to deal with processes at a higher conceptual level than that of the primitive operations of the language, the ability to construct compound data objects enables us to deal with data at a higher conceptual level than that of the primitive data objects of the language.</p>
+
+ <p><a name="%_idx_1260"></a>Consider the task of designing a system to perform arithmetic with rational numbers. We could imagine an operation <tt>add-rat</tt> that takes two rational numbers and produces their sum. In terms of simple data, a rational number can be thought of as two integers: a numerator and a denominator. Thus, we could design a program in which each rational number would be represented by two integers (a numerator and a denominator) and where <tt>add-rat</tt> would be implemented by two procedures (one producing the numerator of the sum and one producing the denominator). But this would be awkward, because we would then need to explicitly keep track of which numerators corresponded to which denominators. In a system intended to perform many operations on many rational numbers, such bookkeeping details would clutter the programs substantially, to say nothing of what they would do to our minds. It would be much better if we could “glue together” a numerator and denominator to form a pair—a <em>compound data object</em>—that our programs could manipulate in a way that would be consistent with regarding a rational number as a single conceptual unit.</p>
+
+ <p>The use of compound data also enables us to increase the modularity of our programs. If we can manipulate rational numbers directly as objects in their own right, then we can separate the part of our program that deals with rational numbers per se from the details of how rational numbers may be represented as pairs of integers. The general technique of isolating the parts of a program that deal with how data objects are represented from the parts of a program that deal with how data objects are used is a powerful design methodology called <a name="%_idx_1262"></a><em>data abstraction</em>. We will see how data abstraction makes programs much easier to design, maintain, and modify.</p>
+
+ <p>The use of compound data leads to a real increase in the expressive power of our programming language. Consider the idea of forming a “linear combination” <em>a</em><em>x</em> + <em>b</em><em>y</em>. We might like to write a procedure that would accept <em>a</em>, <em>b</em>, <em>x</em>, and <em>y</em> as arguments and return the value of <em>a</em><em>x</em> + <em>b</em><em>y</em>. This presents no difficulty if the arguments are to be numbers, because we can readily define the procedure</p>
+
+ <p><tt>(define&nbsp;(linear-combination&nbsp;a&nbsp;b&nbsp;x&nbsp;y)&nbsp;<br />
+ &nbsp;&nbsp;(+&nbsp;(*&nbsp;a&nbsp;x)&nbsp;(*&nbsp;b&nbsp;y)))<br /></tt></p>
+
+ <p>But suppose we are not concerned only with numbers. Suppose we would like to express, in procedural terms, the idea that one can form linear combinations whenever addition and multiplication are defined—for rational numbers, complex numbers, polynomials, or whatever. We could express this as a procedure of the form</p>
+
+ <p><tt>(define&nbsp;(linear-combination&nbsp;a&nbsp;b&nbsp;x&nbsp;y)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
+ &nbsp;&nbsp;(add&nbsp;(mul&nbsp;a&nbsp;x)&nbsp;(mul&nbsp;b&nbsp;y)))&nbsp;<br /></tt></p>
+
+ <p>where <tt>add</tt> and <tt>mul</tt> are not the primitive procedures <tt>+</tt> and <tt>*</tt> but rather more complex things that will perform the appropriate operations for whatever kinds of data we pass in as the arguments <tt>a</tt>, <tt>b</tt>, <tt>x</tt>, and <tt>y</tt>. The key point is that the only thing <tt>linear-combination</tt> should need to know about <tt>a</tt>, <tt>b</tt>, <tt>x</tt>, and <tt>y</tt> is that the procedures <tt>add</tt> and <tt>mul</tt> will perform the appropriate manipulations. From the perspective of the procedure <tt>linear-combination</tt>, it is irrelevant what <tt>a</tt>, <tt>b</tt>, <tt>x</tt>, and <tt>y</tt> are and even more irrelevant how they might happen to be represented in terms of more primitive data. This same example shows why it is important that our programming language provide the ability to manipulate compound objects directly: Without this, there is no way for a procedure such as <tt>linear-combination</tt> to pass its arguments along to <tt>add</tt> and <tt>mul</tt> without having to know their detailed structure.<a href="#footnote_Temp_131" name="call_footnote_Temp_131" id="call_footnote_Temp_131"><sup><small>1</small></sup></a> We begin this chapter by implementing the rational-number arithmetic system mentioned above. This will form the background for our discussion of compound data and data abstraction. As with compound procedures, the main issue to be addressed is that of abstraction as a technique for coping with complexity, and we will see how data abstraction enables us to erect suitable <a name="%_idx_1264"></a><em>abstraction barriers</em> between different parts of a program.</p>
+
+ <p>We will see that the key to forming compound data is that a programming language should provide some kind of “glue” so that data objects can be combined to form more complex data objects. There are many possible kinds of glue. Indeed, we will discover how to form compound data using no special “data” operations at all, only procedures. This will further blur the distinction between “procedure” and “data,” which was already becoming tenuous toward the end of chapter&nbsp;1. We will also explore some conventional techniques for representing sequences and trees. One key idea in dealing with compound data is the notion of <a name="%_idx_1266"></a><em>closure</em>—that the glue we use for combining data objects should allow us to combine not only primitive data objects, but compound data objects as well. Another key idea is that compound data objects can serve as <a name="%_idx_1268"></a><em>conventional interfaces</em> for combining program modules in mix-and-match ways. We illustrate some of these ideas by presenting a simple graphics language that exploits closure.</p>
+
+ <p>We will then augment the representational power of our language by introducing <a name="%_idx_1270"></a><a name="%_idx_1272"></a><em>symbolic expressions</em>—data whose elementary parts can be arbitrary symbols rather than only numbers. We explore various alternatives for representing sets of objects. We will find that, just as a given numerical function can be computed by many different computational processes, there are many ways in which a given data structure can be represented in terms of simpler objects, and the choice of representation can have significant impact on the time and space requirements of processes that manipulate the data. We will investigate these ideas in the context of symbolic differentiation, the representation of sets, and the encoding of information.</p>
+
+ <p>Next we will take up the problem of working with data that may be represented differently by different parts of a program. This leads to the need to implement <a name="%_idx_1274"></a><a name="%_idx_1276"></a><em>generic operations</em>, which must handle many different types of data. Maintaining modularity in the presence of generic operations requires more powerful abstraction barriers than can be erected with simple data abstraction alone. In particular, we introduce <em>data-directed programming</em> as a technique that allows individual data representations to be designed in isolation and then combined <a name="%_idx_1278"></a><em>additively</em> (i.e., without modification). To illustrate the power of this approach to system design, we close the chapter by applying what we have learned to the implementation of a package for performing symbolic arithmetic on polynomials, in which the coefficients of the polynomials can be integers, rational numbers, complex numbers, and even other polynomials.</p>
+
+ <div class="smallprint">
+ <hr />
+ </div>
+
+ <div class="footnote">
+ <p><a href="#call_footnote_Temp_131" name="footnote_Temp_131" id="footnote_Temp_131"><sup><small>1</small></sup></a> The ability to directly manipulate procedures provides an analogous increase in the expressive power of a programming language. For example, in section&nbsp;<a href="book-Z-H-12.html#%_sec_1.3.1">1.3.1</a> we introduced the <tt>sum</tt> procedure, which takes a procedure <tt>term</tt> as an argument and computes the sum of the values of <tt>term</tt> over some specified interval. In order to define <tt>sum</tt>, it is crucial that we be able to speak of a procedure such as <tt>term</tt> as an entity in its own right, without regard for how <tt>term</tt> might be expressed with more primitive operations. Indeed, if we did not have the notion of “a procedure,” it is doubtful that we would ever even think of the possibility of defining an operation such as <tt>sum</tt>. Moreover, insofar as performing the summation is concerned, the details of how <tt>term</tt> may be constructed from more primitive operations are irrelevant.</p>
+ </div>
</body>
</html>
View
1,256 content/book-Z-H-14.html
@@ -1,882 +1,416 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html>
+<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Generated from TeX source by tex2page, v 4o,
(c) Dorai Sitaram, http://www.cs.rice.edu/~dorai/tex2page -->
<head>
- <meta name="generator" content="HTML Tidy for Linux (vers 7 December 2008), see www.w3.org" />
+ <meta name="generator" content="HTML Tidy for Linux (vers 7 December 2008), see www.w3.org" />
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
- <title>Structure and Interpretation of Computer Programs</title>
- <link href="book-Z-C.css" title="default" rel="stylesheet" type="text/css" />
- <meta name="robots" content="noindex,follow" />
+ <title>Structure and Interpretation of Computer Programs</title>
+ <link href="book-Z-C.css" title="default" rel="stylesheet" type="text/css" />
+ <meta name="robots" content="noindex,follow" />
</head>
<body>
- <mbp:pagebreak />
-
- <p><a name="%_sec_2.1"></a></p>
-
- <h2><a href="book-Z-H-4.html#%_toc_%_sec_2.1">2.1&nbsp;&nbsp;Introduction to
- Data Abstraction</a></h2>
+ <mbp:pagebreak />
- <p>In section&nbsp;<a href="book-Z-H-10.html#%_sec_1.1.8">1.1.8</a>, we noted that a
- procedure used as an element in creating a more complex procedure
- could be regarded not only as a collection of particular
- operations but also as a procedural abstraction. That is, the
- details of how the procedure was implemented could be suppressed,
- and the particular procedure itself could be replaced by any
- other procedure with the same overall behavior. In other words,
- we could make an abstraction that would separate the way the
- procedure would be used from the details of how the procedure
- would be implemented in terms of more primitive procedures. The
- analogous notion for compound data is called <a name="%_idx_1280"></a><em>data abstraction</em>. Data abstraction is a
- methodology that enables us to isolate how a compound data object
- is used from the details of how it is constructed from more
- primitive data objects.</p>
+ <p><a name="%_sec_2.1"></a></p>
- <p>The basic idea of data abstraction is to structure the
- programs that are to use compound data objects so that they
- operate on <a name="%_idx_1282"></a><a name="%_idx_1284"></a>``abstract data.'' That is, our programs should
- use data in such a way as to make no assumptions about the data
- that are not strictly necessary for performing the task at hand.
- At the same time, a <a name="%_idx_1286"></a><a name="%_idx_1288"></a>``concrete'' data representation is defined
- independent of the programs that use the data. The interface
- between these two parts of our system will be a set of
- procedures, called <a name="%_idx_1290"></a><em>selectors</em>
- and <a name="%_idx_1292"></a><em>constructors</em>, that
- implement the abstract data in terms of the concrete
- representation. To illustrate this technique, we will consider
- how to design a set of procedures for manipulating rational
- numbers.</p>
+ <h2><a href="book-Z-H-4.html#%_toc_%_sec_2.1">2.1&nbsp;&nbsp;Introduction to Data Abstraction</a></h2>
- <p><a name="%_sec_2.1.1"></a></p>
+ <p>In section&nbsp;<a href="book-Z-H-10.html#%_sec_1.1.8">1.1.8</a>, we noted that a procedure used as an element in creating a more complex procedure could be regarded not only as a collection of particular operations but also as a procedural abstraction. That is, the details of how the procedure was implemented could be suppressed, and the particular procedure itself could be replaced by any other procedure with the same overall behavior. In other words, we could make an abstraction that would separate the way the procedure would be used from the details of how the procedure would be implemented in terms of more primitive procedures. The analogous notion for compound data is called <a name="%_idx_1280"></a><em>data abstraction</em>. Data abstraction is a methodology that enables us to isolate how a compound data object is used from the details of how it is constructed from more primitive data objects.</p>
- <h3><a href="book-Z-H-4.html#%_toc_%_sec_2.1.1">2.1.1&nbsp;&nbsp;Example:
- Arithmetic Operations for Rational Numbers</a></h3>
+ <p>The basic idea of data abstraction is to structure the programs that are to use compound data objects so that they operate on <a name="%_idx_1282"></a><a name="%_idx_1284"></a>“abstract data.” That is, our programs should use data in such a way as to make no assumptions about the data that are not strictly necessary for performing the task at hand. At the same time, a <a name="%_idx_1286"></a><a name="%_idx_1288"></a>“concrete” data representation is defined independent of the programs that use the data. The interface between these two parts of our system will be a set of procedures, called <a name="%_idx_1290"></a><em>selectors</em> and <a name="%_idx_1292"></a><em>constructors</em>, that implement the abstract data in terms of the concrete representation. To illustrate this technique, we will consider how to design a set of procedures for manipulating rational numbers.</p>
- <p><a name="%_idx_1294"></a><a name="%_idx_1296"></a><a name="%_idx_1298"></a>Suppose we want to do arithmetic with rational
- numbers. We want to be able to add, subtract, multiply, and
- divide them and to test whether two rational numbers are
- equal.</p>
+ <p><a name="%_sec_2.1.1"></a></p>
- <p>Let us begin by assuming that we already have a way of
- constructing a rational number from a numerator and a
- denominator. We also assume that, given a rational number, we
- have a way of extracting (or selecting) its numerator and its
- denominator. Let us further assume that the constructor and
- selectors are available as procedures:</p>
+ <h3><a href="book-Z-H-4.html#%_toc_%_sec_2.1.1">2.1.1&nbsp;&nbsp;Example: Arithmetic Operations for Rational Numbers</a></h3>
+
+ <p><a name="%_idx_1294"></a><a name="%_idx_1296"></a><a name="%_idx_1298"></a>Suppose we want to do arithmetic with rational numbers. We want to be able to add, subtract, multiply, and divide them and to test whether two rational numbers are equal.</p>
+
+ <p>Let us begin by assuming that we already have a way of constructing a rational number from a numerator and a denominator. We also assume that, given a rational number, we have a way of extracting (or selecting) its numerator and its denominator. Let us further assume that the constructor and selectors are available as procedures:</p>
+
+ <ul>
+ <li>
+ <tt>(make-rat &lt;<em>n</em>&gt; &lt;<em>d</em>&gt;)</tt> returns the rational number whose numerator is the integer <tt>&lt;<em>n</em>&gt;</tt> and whose denominator is the integer <tt>&lt;<em>d</em>&gt;</tt>.
+
+ <p><a name="%_idx_1302"></a></p>
+ </li>
+
+ <li>
+ <tt>(numer &lt;<em>x</em>&gt;)</tt> returns the numerator of the rational number <tt>&lt;<em>x</em>&gt;</tt>.
+
+ <p><a name="%_idx_1304"></a></p>
+ </li>
+
+ <li><tt>(denom &lt;<em>x</em>&gt;)</tt> returns the denominator of the rational number <tt>&lt;<em>x</em>&gt;</tt>.</li>
+ </ul>
+
+ <p>We are using here a powerful strategy of synthesis: <a name="%_idx_1306"></a><em>wishful thinking</em>. We haven’t yet said how a rational number is represented, or how the procedures <tt>numer</tt>, <tt>denom</tt>, and <tt>make-rat</tt> should be implemented. Even so, if we did have these three procedures, we could then add, subtract, multiply, divide, and test equality by using the following relations:</p>
+
+ <div align="left">
+ <img src="ch2-Z-G-1.gif" border="0" />
+ </div>
+
+ <div align="left">
+ <img src="ch2-Z-G-2.gif" border="0" />
+ </div>
+
+ <div align="left">
+ <img src="ch2-Z-G-3.gif" border="0" />
+ </div>
+
+ <div align="left">
+ <img src="ch2-Z-G-4.gif" border="0" />
+ </div>
+
+ <div align="left">
+ <img src="ch2-Z-G-5.gif" border="0" />
+ </div>
+
+ <p>We can express these rules as procedures:</p>
+
+ <p><tt><a name="%_idx_1308"></a>(define&nbsp;(add-rat&nbsp;x&nbsp;y)<br />
+ &nbsp;&nbsp;(make-rat&nbsp;(+&nbsp;(*&nbsp;(numer&nbsp;x)&nbsp;(denom&nbsp;y))<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(numer&nbsp;y)&nbsp;(denom&nbsp;x)))<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(denom&nbsp;x)&nbsp;(denom&nbsp;y))))<br />
+ <a name="%_idx_1310"></a>(define&nbsp;(sub-rat&nbsp;x&nbsp;y)<br />
+ &nbsp;&nbsp;(make-rat&nbsp;(-&nbsp;(*&nbsp;(numer&nbsp;x)&nbsp;(denom&nbsp;y))<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(numer&nbsp;y)&nbsp;(denom&nbsp;x)))<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(denom&nbsp;x)&nbsp;(denom&nbsp;y))))<br />
+ <a name="%_idx_1312"></a>(define&nbsp;(mul-rat&nbsp;x&nbsp;y)<br />
+ &nbsp;&nbsp;(make-rat&nbsp;(*&nbsp;(numer&nbsp;x)&nbsp;(numer&nbsp;y))<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(denom&nbsp;x)&nbsp;(denom&nbsp;y))))<br />
+ <a name="%_idx_1314"></a>(define&nbsp;(div-rat&nbsp;x&nbsp;y)<br />
+ &nbsp;&nbsp;(make-rat&nbsp;(*&nbsp;(numer&nbsp;x)&nbsp;(denom&nbsp;y))<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(denom&nbsp;x)&nbsp;(numer&nbsp;y))))<br />
+ <a name="%_idx_1316"></a>(define&nbsp;(equal-rat?&nbsp;x&nbsp;y)<br />
+ &nbsp;&nbsp;(=&nbsp;(*&nbsp;(numer&nbsp;x)&nbsp;(denom&nbsp;y))<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(numer&nbsp;y)&nbsp;(denom&nbsp;x))))<br /></tt></p>
+
+ <p>Now we have the operations on rational numbers defined in terms of the selector and constructor procedures <tt>numer</tt>, <tt>denom</tt>, and <tt>make-rat</tt>. But we haven’t yet defined these. What we need is some way to glue together a numerator and a denominator to form a rational number.</p>
+
+ <p><a name="%_sec_Temp_132"></a></p>
+
+ <h4><a href="book-Z-H-4.html#%_toc_%_sec_Temp_132">Pairs</a></h4>
+
+ <p>To enable us to implement the concrete level of our data abstraction, our language provides a compound structure called a <a name="%_idx_1318"></a><em>pair</em>, which can be constructed with the primitive procedure <a name="%_idx_1320"></a><a name="%_idx_1322"></a><tt>cons</tt>. This procedure takes two arguments and returns a compound data object that contains the two arguments as parts. Given a pair, we can extract the parts using the primitive procedures <a name="%_idx_1324"></a><a name="%_idx_1326"></a><tt>car</tt> and <a name="%_idx_1328"></a><a name="%_idx_1330"></a><tt>cdr</tt>.<a href="#footnote_Temp_133" name="call_footnote_Temp_133" id="call_footnote_Temp_133"><sup><small>2</small></sup></a> Thus, we can use <tt>cons</tt>, <tt>car</tt>, and <tt>cdr</tt> as follows:</p>
+
+ <p><tt>(define&nbsp;x&nbsp;(cons&nbsp;1&nbsp;2))<br />
+ <br />
+ (car&nbsp;x)<br />
+ <i>1</i><br />
+ <br />
+ (cdr&nbsp;x)<br />
+ <i>2</i><br /></tt></p>
+
+ <p>Notice that a pair is a data object that can be given a name and manipulated, just like a primitive data object. Moreover, <tt>cons</tt> can be used to form pairs whose elements are pairs, and so on:</p>
+
+ <p><tt>(define&nbsp;x&nbsp;(cons&nbsp;1&nbsp;2))<br />
+ <br />
+ (define&nbsp;y&nbsp;(cons&nbsp;3&nbsp;4))<br />
+ <br />
+ (define&nbsp;z&nbsp;(cons&nbsp;x&nbsp;y))<br />
+ <br />
+ (car&nbsp;(car&nbsp;z))<br />
+ <i>1</i><br />
+ <br />
+ (car&nbsp;(cdr&nbsp;z))<br />
+ <i>3</i><br /></tt></p>
+
+ <p>In section&nbsp;<a href="book-Z-H-15.html#%_sec_2.2">2.2</a> we will see how this ability to combine pairs means that pairs can be used as general-purpose building blocks to create all sorts of complex data structures. The single compound-data primitive <em>pair</em>, implemented by the procedures <tt>cons</tt>, <tt>car</tt>, and <tt>cdr</tt>, is the only glue we need. Data objects constructed from pairs are called <a name="%_idx_1342"></a><a name="%_idx_1344"></a><em>list-structured</em> data.</p>
+
+ <p><a name="%_sec_Temp_134"></a></p>
+
+ <h4><a href="book-Z-H-4.html#%_toc_%_sec_Temp_134">Representing rational numbers</a></h4>
+
+ <p><a name="%_idx_1346"></a>Pairs offer a natural way to complete the rational-number system. Simply represent a rational number as a pair of two integers: a numerator and a denominator. Then <tt>make-rat</tt>, <tt>numer</tt>, and <tt>denom</tt> are readily implemented as follows:<a href="#footnote_Temp_135" name="call_footnote_Temp_135" id="call_footnote_Temp_135"><sup><small>3</small></sup></a></p>
+
+ <p><tt><a name="%_idx_1348"></a>(define&nbsp;(make-rat&nbsp;n&nbsp;d)&nbsp;(cons&nbsp;n&nbsp;d))<br />
+ <br />
+ <a name="%_idx_1350"></a>(define&nbsp;(numer&nbsp;x)&nbsp;(car&nbsp;x))<br />
+ <br />
+ <a name="%_idx_1352"></a>(define&nbsp;(denom&nbsp;x)&nbsp;(cdr&nbsp;x))<br /></tt></p>
+
+ <p>Also, in order to display the results of our computations, we can <a name="%_idx_1354"></a>print rational numbers by printing the numerator, a slash, and the denominator:<a href="#footnote_Temp_136" name="call_footnote_Temp_136" id="call_footnote_Temp_136"><sup><small>4</small></sup></a></p>
+
+ <p><tt><a name="%_idx_1370"></a>(define&nbsp;(print-rat&nbsp;x)<br />
+ &nbsp;&nbsp;(newline)<br />
+ &nbsp;&nbsp;(display&nbsp;(numer&nbsp;x))<br />
+ &nbsp;&nbsp;(display&nbsp;”/”)<br />
+ &nbsp;&nbsp;(display&nbsp;(denom&nbsp;x)))<br /></tt></p>
+
+ <p>Now we can try our rational-number procedures:</p>
+
+ <p><tt>(define&nbsp;one-half&nbsp;(make-rat&nbsp;1&nbsp;2))<br />
+ <br />
+ (print-rat&nbsp;one-half)<br />
+ <i>1/2</i><br />
+ <br />
+ (define&nbsp;one-third&nbsp;(make-rat&nbsp;1&nbsp;3))<br />
+ (print-rat&nbsp;(add-rat&nbsp;one-half&nbsp;one-third))<br />
+ <i>5/6</i><br />
+ <br />
+ (print-rat&nbsp;(mul-rat&nbsp;one-half&nbsp;one-third))<br />
+ <i>1/6</i><br />
+ <br />
+ (print-rat&nbsp;(add-rat&nbsp;one-third&nbsp;one-third))<br />
+ <i>6/9</i><br /></tt></p>
+
+ <p><a name="%_idx_1372"></a><a name="%_idx_1374"></a>As the final example shows, our rational-number implementation does not reduce rational numbers to lowest terms. We can remedy this by changing <tt>make-rat</tt>. If we have a <a name="%_idx_1376"></a><tt>gcd</tt> procedure like the one in section&nbsp;<a href="book-Z-H-11.html#%_sec_1.2.5">1.2.5</a> that produces the greatest common divisor of two integers, we can use <tt>gcd</tt> to reduce the numerator and the denominator to lowest terms before constructing the pair:</p>
+
+ <p><tt><a name="%_idx_1378"></a>(define&nbsp;(make-rat&nbsp;n&nbsp;d)<br />
+ &nbsp;&nbsp;(let&nbsp;((g&nbsp;(gcd&nbsp;n&nbsp;d)))<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;(cons&nbsp;(/&nbsp;n&nbsp;g)&nbsp;(/&nbsp;d&nbsp;g))))<br /></tt></p>
+
+ <p>Now we have</p>
+
+ <p><tt>(print-rat&nbsp;(add-rat&nbsp;one-third&nbsp;one-third))<br />
+ <i>2/3</i><br /></tt></p>
+
+ <p>as desired. This modification was accomplished by changing the constructor <tt>make-rat</tt> without changing any of the procedures (such as <tt>add-rat</tt> and <tt>mul-rat</tt>) that implement the actual operations.</p>
+
+ <p><a name="%_thm_2.1"></a> <b>Exercise 2.1.</b>&nbsp;&nbsp;Define a better version of <tt>make-rat</tt> that handles both positive and negative arguments. <tt>Make-rat</tt> should normalize the sign so that if the rational number is positive, both the numerator and denominator are positive, and if the rational number is negative, only the numerator is negative.</p>
+
+ <p><a name="%_sec_2.1.2"></a></p>
+
+ <h3><a href="book-Z-H-4.html#%_toc_%_sec_2.1.2">2.1.2&nbsp;&nbsp;Abstraction Barriers</a></h3>
+
+ <p><a name="%_idx_1380"></a>Before continuing with more examples of compound data and data abstraction, let us consider some of the issues raised by the rational-number example. We defined the rational-number operations in terms of a constructor <tt>make-rat</tt> and selectors <tt>numer</tt> and <tt>denom</tt>. In general, the underlying idea of data abstraction is to identify for each type of data object a basic set of operations in terms of which all manipulations of data objects of that type will be expressed, and then to use only those operations in manipulating the data.</p>
+
+ <p>We can envision the structure of the rational-number system as shown in figure&nbsp;<a href="#%_fig_2.1">2.1</a>. The horizontal lines represent <em>abstraction barriers</em> that isolate different “levels” of the system. At each level, the barrier separates the programs (above) that use the data abstraction from the programs (below) that implement the data abstraction. Programs that use rational numbers manipulate them solely in terms of the procedures supplied “for public use” by the rational-number package: <tt>add-rat</tt>, <tt>sub-rat</tt>, <tt>mul-rat</tt>, <tt>div-rat</tt>, and <tt>equal-rat?</tt>. These, in turn, are implemented solely in terms of the <a name="%_idx_1382"></a><a name="%_idx_1384"></a>constructor and selectors <tt>make-rat</tt>, <tt>numer</tt>, and <tt>denom</tt>, which themselves are implemented in terms of pairs. The details of how pairs are implemented are irrelevant to the rest of the rational-number package so long as pairs can be manipulated by the use of <tt>cons</tt>, <tt>car</tt>, and <tt>cdr</tt>. In effect, procedures at each level are the interfaces that define the abstraction barriers and connect the different levels.</p>
+
+ <p><a name="%_fig_2.1"></a></p>
+
+ <div align="left">
+ <div align="left">
+ <b>Figure 2.1:</b>&nbsp;&nbsp;Data-abstraction barriers in the rational-number package.
+ </div>
+
+ <table width="100%">
+ <tr>
+ <td>
+ <div align="left">
+ <img src="ch2-Z-G-6.gif" border="0" />&nbsp;
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td></td>
+ </tr>
+ </table>
+ </div>
+
+ <p>This simple idea has many advantages. One advantage is that it makes programs much easier to maintain and to modify. Any complex data structure can be represented in a variety of ways with the primitive data structures provided by a programming language. Of course, the choice of representation influences the programs that operate on it; thus, if the representation were to be changed at some later time, all such programs might have to be modified accordingly. This task could be time-consuming and expensive in the case of large programs unless the dependence on the representation were to be confined by design to a very few program modules.</p>
+
+ <p><a name="%_idx_1386"></a><a name="%_idx_1388"></a>For example, an alternate way to address the problem of reducing rational numbers to lowest terms is to perform the reduction whenever we access the parts of a rational number, rather than when we construct it. This leads to different constructor and selector procedures:</p>
+
+ <p><tt><a name="%_idx_1390"></a>(define&nbsp;(make-rat&nbsp;n&nbsp;d)<br />
+ &nbsp;&nbsp;(cons&nbsp;n&nbsp;d))<br />
+ <a name="%_idx_1392"></a>(define&nbsp;(numer&nbsp;x)<br />
+ &nbsp;&nbsp;(let&nbsp;((g&nbsp;(gcd&nbsp;(car&nbsp;x)&nbsp;(cdr&nbsp;x))))<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;(/&nbsp;(car&nbsp;x)&nbsp;g)))<br />
+ <a name="%_idx_1394"></a>(define&nbsp;(denom&nbsp;x)<br />
+ &nbsp;&nbsp;(let&nbsp;((g&nbsp;(gcd&nbsp;(car&nbsp;x)&nbsp;(cdr&nbsp;x))))<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;(/&nbsp;(cdr&nbsp;x)&nbsp;g)))<br /></tt></p>
+
+ <p>The difference between this implementation and the previous one lies in when we compute the <tt>gcd</tt>. If in our typical use of rational numbers we access the numerators and denominators of the same rational numbers many times, it would be preferable to compute the <tt>gcd</tt> when the rational numbers are constructed. If not, we may be better off waiting until access time to compute the <tt>gcd</tt>. In any case, when we change from one representation to the other, the procedures <tt>add-rat</tt>, <tt>sub-rat</tt>, and so on do not have to be modified at all.</p>
+
+ <p>Constraining the dependence on the representation to a few interface procedures helps us design programs as well as modify them, because it allows us to maintain the flexibility to consider alternate implementations. To continue with our simple example, suppose we are designing a rational-number package and we can’t decide initially whether to perform the <tt>gcd</tt> at construction time or at selection time. The data-abstraction methodology gives us a way to defer that decision without losing the ability to make progress on the rest of the system.</p>
+
+ <p><a name="%_thm_2.2"></a> <b>Exercise 2.2.</b>&nbsp;&nbsp;Consider the problem of representing <a name="%_idx_1396"></a>line segments in a plane. Each segment is represented as a pair of points: a starting point and an ending point. Define a constructor <a name="%_idx_1398"></a><tt>make-segment</tt> and selectors <a name="%_idx_1400"></a><tt>start-segment</tt> and <a name="%_idx_1402"></a><tt>end-segment</tt> that define the representation of segments in terms of points. Furthermore, a point <a name="%_idx_1404"></a>can be represented as a pair of numbers: the <em>x</em> coordinate and the <em>y</em> coordinate. Accordingly, specify a constructor <a name="%_idx_1406"></a><tt>make-point</tt> and selectors <tt>x-point</tt> and <tt>y-point</tt> that define this representation. Finally, using your selectors and constructors, define a procedure <a name="%_idx_1408"></a><tt>midpoint-segment</tt> that takes a line segment as argument and returns its midpoint (the point whose coordinates are the average of the coordinates of the endpoints). To try your procedures, you’ll need a way to print points:</p>
+
+ <p><tt><a name="%_idx_1410"></a>(define&nbsp;(print-point&nbsp;p)<br />
+ &nbsp;&nbsp;(newline)<br />
+ &nbsp;&nbsp;(display&nbsp;”(”)<br />
+ &nbsp;&nbsp;(display&nbsp;(x-point&nbsp;p))<br />
+ &nbsp;&nbsp;(display&nbsp;”,”)<br />
+ &nbsp;&nbsp;(display&nbsp;(y-point&nbsp;p))<br />
+ &nbsp;&nbsp;(display&nbsp;”)”))<br /></tt></p>
+
+ <p><a name="%_thm_2.3"></a> <b>Exercise 2.3.</b>&nbsp;&nbsp;<a name="%_idx_1412"></a>Implement a representation for rectangles in a plane. (Hint: You may want to make use of exercise&nbsp;<a href="#%_thm_2.2">2.2</a>.) In terms of your constructors and selectors, create procedures that compute the perimeter and the area of a given rectangle. Now implement a different representation for rectangles. Can you design your system with suitable abstraction barriers, so that the same perimeter and area procedures will work using either representation?</p>
+
+ <p><a name="%_sec_2.1.3"></a></p>
+
+ <h3><a href="book-Z-H-4.html#%_toc_%_sec_2.1.3">2.1.3&nbsp;&nbsp;What Is Meant by Data?</a></h3>
+
+ <p><a name="%_idx_1414"></a> We began the rational-number implementation in section&nbsp;<a href="#%_sec_2.1.1">2.1.1</a> by implementing the rational-number operations <tt>add-rat</tt>, <tt>sub-rat</tt>, and so on in terms of three unspecified procedures: <tt>make-rat</tt>, <tt>numer</tt>, and <tt>denom</tt>. At that point, we could think of the operations as being defined in terms of data objects—numerators, denominators, and rational numbers—whose behavior was specified by the latter three procedures.</p>
+
+ <p>But exactly what is meant by <em>data</em>? It is not enough to say “whatever is implemented by the given selectors and constructors.” Clearly, not every arbitrary set of three procedures can serve as an appropriate basis for the rational-number implementation. We need to guarantee that, <a name="%_idx_1416"></a><a name="%_idx_1418"></a><a name="%_idx_1420"></a>if we construct a rational number <tt>x</tt> from a pair of integers <tt>n</tt> and <tt>d</tt>, then extracting the <tt>numer</tt> and the <tt>denom</tt> of <tt>x</tt> and dividing them should yield the same result as dividing <tt>n</tt> by <tt>d</tt>. In other words, <tt>make-rat</tt>, <tt>numer</tt>, and <tt>denom</tt> must satisfy the condition that, for any integer <tt>n</tt> and any non-zero integer <tt>d</tt>, if <tt>x</tt> is (<tt>make-rat n d</tt>), then</p>
- <ul>
- <li>
- <tt>(make-rat &lt;<em>n</em>&gt; &lt;<em>d</em>&gt;)</tt>
- returns the rational number whose numerator is the integer
- <tt>&lt;<em>n</em>&gt;</tt> and whose denominator is the
- integer <tt>&lt;<em>d</em>&gt;</tt>.
-
- <p><a name="%_idx_1302"></a></p>
- </li>
-
- <li>
- <tt>(numer &lt;<em>x</em>&gt;)</tt> returns the numerator of
- the rational number <tt>&lt;<em>x</em>&gt;</tt>.
-
- <p><a name="%_idx_1304"></a></p>
- </li>
-
- <li><tt>(denom &lt;<em>x</em>&gt;)</tt> returns the denominator
- of the rational number <tt>&lt;<em>x</em>&gt;</tt>.</li>
- </ul>
-
- <p>We are using here a powerful strategy of synthesis: <a name="%_idx_1306"></a><em>wishful thinking</em>. We haven't yet said
- how a rational number is represented, or how the procedures
- <tt>numer</tt>, <tt>denom</tt>, and <tt>make-rat</tt> should be
- implemented. Even so, if we did have these three procedures, we
- could then add, subtract, multiply, divide, and test equality by
- using the following relations:</p>
-
- <div align="left"><img src="ch2-Z-G-1.gif" border="0" /></div>
-
- <div align="left"><img src="ch2-Z-G-2.gif" border="0" /></div>
-
- <div align="left"><img src="ch2-Z-G-3.gif" border="0" /></div>
-
- <div align="left"><img src="ch2-Z-G-4.gif" border="0" /></div>
-
- <div align="left"><img src="ch2-Z-G-5.gif" border="0" /></div>
-
- <p>We can express these rules as procedures:</p>
-
- <p><tt><a name="%_idx_1308"></a>(define&nbsp;(add-rat&nbsp;x&nbsp;y)<br />
- &nbsp;&nbsp;(make-rat&nbsp;(+&nbsp;(*&nbsp;(numer&nbsp;x)&nbsp;(denom&nbsp;y))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(numer&nbsp;y)&nbsp;(denom&nbsp;x)))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(denom&nbsp;x)&nbsp;(denom&nbsp;y))))<br />
-
- <a name="%_idx_1310"></a>(define&nbsp;(sub-rat&nbsp;x&nbsp;y)<br />
- &nbsp;&nbsp;(make-rat&nbsp;(-&nbsp;(*&nbsp;(numer&nbsp;x)&nbsp;(denom&nbsp;y))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(numer&nbsp;y)&nbsp;(denom&nbsp;x)))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(denom&nbsp;x)&nbsp;(denom&nbsp;y))))<br />
-
- <a name="%_idx_1312"></a>(define&nbsp;(mul-rat&nbsp;x&nbsp;y)<br />
- &nbsp;&nbsp;(make-rat&nbsp;(*&nbsp;(numer&nbsp;x)&nbsp;(numer&nbsp;y))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(denom&nbsp;x)&nbsp;(denom&nbsp;y))))<br />
-
- <a name="%_idx_1314"></a>(define&nbsp;(div-rat&nbsp;x&nbsp;y)<br />
- &nbsp;&nbsp;(make-rat&nbsp;(*&nbsp;(numer&nbsp;x)&nbsp;(denom&nbsp;y))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(denom&nbsp;x)&nbsp;(numer&nbsp;y))))<br />
-
- <a name="%_idx_1316"></a>(define&nbsp;(equal-rat?&nbsp;x&nbsp;y)<br />
- &nbsp;&nbsp;(=&nbsp;(*&nbsp;(numer&nbsp;x)&nbsp;(denom&nbsp;y))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;(numer&nbsp;y)&nbsp;(denom&nbsp;x))))<br />
- </tt></p>
-
- <p>Now we have the operations on rational numbers defined in
- terms of the selector and constructor procedures <tt>numer</tt>,
- <tt>denom</tt>, and <tt>make-rat</tt>. But we haven't yet defined
- these. What we need is some way to glue together a numerator and
- a denominator to form a rational number.</p>
-
- <p><a name="%_sec_Temp_132"></a></p>
-
- <h4><a href="book-Z-H-4.html#%_toc_%_sec_Temp_132">Pairs</a></h4>
-
- <p>To enable us to implement the concrete level of our data
- abstraction, our language provides a compound structure called a
- <a name="%_idx_1318"></a><em>pair</em>, which can be constructed
- with the primitive procedure <a name="%_idx_1320"></a><a name="%_idx_1322"></a><tt>cons</tt>. This procedure takes two
- arguments and returns a compound data object that contains the
- two arguments as parts. Given a pair, we can extract the parts
- using the primitive procedures <a name="%_idx_1324"></a><a name="%_idx_1326"></a><tt>car</tt> and <a name="%_idx_1328"></a><a name="%_idx_1330"></a><tt>cdr</tt>.<a href="#footnote_Temp_133" name="call_footnote_Temp_133" id="call_footnote_Temp_133"><sup><small>2</small></sup></a> Thus, we
- can use <tt>cons</tt>, <tt>car</tt>, and <tt>cdr</tt> as
- follows:</p>
-
- <p><tt>(define&nbsp;x&nbsp;(cons&nbsp;1&nbsp;2))<br />
- <br />
- (car&nbsp;x)<br />
- <i>1</i><br />
- <br />
- (cdr&nbsp;x)<br />
- <i>2</i><br /></tt></p>
-
- <p>Notice that a pair is a data object that can be given a name
- and manipulated, just like a primitive data object. Moreover,
- <tt>cons</tt> can be used to form pairs whose elements are pairs,
- and so on:</p>
-
- <p><tt>(define&nbsp;x&nbsp;(cons&nbsp;1&nbsp;2))<br />
- <br />
- (define&nbsp;y&nbsp;(cons&nbsp;3&nbsp;4))<br />
- <br />
- (define&nbsp;z&nbsp;(cons&nbsp;x&nbsp;y))<br />
- <br />
- (car&nbsp;(car&nbsp;z))<br />
- <i>1</i><br />
- <br />
- (car&nbsp;(cdr&nbsp;z))<br />
- <i>3</i><br /></tt></p>
-
- <p>In section&nbsp;<a href="book-Z-H-15.html#%_sec_2.2">2.2</a>
- we will see how this ability to combine pairs means that pairs
- can be used as general-purpose building blocks to create all
- sorts of complex data structures. The single compound-data
- primitive <em>pair</em>, implemented by the procedures
- <tt>cons</tt>, <tt>car</tt>, and <tt>cdr</tt>, is the only glue
- we need. Data objects constructed from pairs are called <a name="%_idx_1342"></a><a name="%_idx_1344"></a><em>list-structured</em> data.</p>
-
- <p><a name="%_sec_Temp_134"></a></p>
-
- <h4><a href="book-Z-H-4.html#%_toc_%_sec_Temp_134">Representing
- rational numbers</a></h4>
-
- <p><a name="%_idx_1346"></a>Pairs offer a natural way to complete
- the rational-number system. Simply represent a rational number as
- a pair of two integers: a numerator and a denominator. Then
- <tt>make-rat</tt>, <tt>numer</tt>, and <tt>denom</tt> are readily
- implemented as follows:<a href="#footnote_Temp_135" name="call_footnote_Temp_135" id="call_footnote_Temp_135"><sup><small>3</small></sup></a></p>
-
- <p><tt><a name="%_idx_1348"></a>(define&nbsp;(make-rat&nbsp;n&nbsp;d)&nbsp;(cons&nbsp;n&nbsp;d))<br />
-
- <br />
- <a name="%_idx_1350"></a>(define&nbsp;(numer&nbsp;x)&nbsp;(car&nbsp;x))<br />
-
- <br />
- <a name="%_idx_1352"></a>(define&nbsp;(denom&nbsp;x)&nbsp;(cdr&nbsp;x))<br />
- </tt></p>
-
- <p>Also, in order to display the results of our computations, we
- can <a name="%_idx_1354"></a>print rational numbers by printing
- the numerator, a slash, and the denominator:<a href="#footnote_Temp_136" name="call_footnote_Temp_136" id="call_footnote_Temp_136"><sup><small>4</small></sup></a></p>
-
- <p><tt><a name="%_idx_1370"></a>(define&nbsp;(print-rat&nbsp;x)<br />
- &nbsp;&nbsp;(newline)<br />
- &nbsp;&nbsp;(display&nbsp;(numer&nbsp;x))<br />
- &nbsp;&nbsp;(display&nbsp;"/")<br />
- &nbsp;&nbsp;(display&nbsp;(denom&nbsp;x)))<br /></tt></p>
-
- <p>Now we can try our rational-number procedures:</p>
-
- <p><tt>(define&nbsp;one-half&nbsp;(make-rat&nbsp;1&nbsp;2))<br />
- <br />
- (print-rat&nbsp;one-half)<br />
- <i>1/2</i><br />
- <br />
- (define&nbsp;one-third&nbsp;(make-rat&nbsp;1&nbsp;3))<br />
- (print-rat&nbsp;(add-rat&nbsp;one-half&nbsp;one-third))<br />
- <i>5/6</i><br />
- <br />
- (print-rat&nbsp;(mul-rat&nbsp;one-half&nbsp;one-third))<br />
- <i>1/6</i><br />
- <br />
- (print-rat&nbsp;(add-rat&nbsp;one-third&nbsp;one-third))<br />
- <i>6/9</i><br /></tt></p>
-
- <p><a name="%_idx_1372"></a><a name="%_idx_1374"></a>As the final
- example shows, our rational-number implementation does not reduce
- rational numbers to lowest terms. We can remedy this by changing
- <tt>make-rat</tt>. If we have a <a name="%_idx_1376"></a><tt>gcd</tt> procedure like the one in
- section&nbsp;<a href="book-Z-H-11.html#%_sec_1.2.5">1.2.5</a>
- that produces the greatest common divisor of two integers, we can
- use <tt>gcd</tt> to reduce the numerator and the denominator to
- lowest terms before constructing the pair:</p>
-
- <p><tt><a name="%_idx_1378"></a>(define&nbsp;(make-rat&nbsp;n&nbsp;d)<br />
- &nbsp;&nbsp;(let&nbsp;((g&nbsp;(gcd&nbsp;n&nbsp;d)))<br />
- &nbsp;&nbsp;&nbsp;&nbsp;(cons&nbsp;(/&nbsp;n&nbsp;g)&nbsp;(/&nbsp;d&nbsp;g))))<br />
- </tt></p>
-
- <p>Now we have</p>
-
- <p>
- <tt>(print-rat&nbsp;(add-rat&nbsp;one-third&nbsp;one-third))<br />
- <i>2/3</i><br /></tt></p>
-
- <p>as desired. This modification was accomplished by changing the
- constructor <tt>make-rat</tt> without changing any of the
- procedures (such as <tt>add-rat</tt> and <tt>mul-rat</tt>) that
- implement the actual operations.</p>
-
- <p><a name="%_thm_2.1"></a> <b>Exercise
- 2.1.</b>&nbsp;&nbsp;Define a better version of <tt>make-rat</tt>
- that handles both positive and negative arguments.
- <tt>Make-rat</tt> should normalize the sign so that if the
- rational number is positive, both the numerator and denominator
- are positive, and if the rational number is negative, only the
- numerator is negative.</p>
-
- <p><a name="%_sec_2.1.2"></a></p>
-
- <h3><a href="book-Z-H-4.html#%_toc_%_sec_2.1.2">2.1.2&nbsp;&nbsp;Abstraction
- Barriers</a></h3>
-
- <p><a name="%_idx_1380"></a>Before continuing with more examples
- of compound data and data abstraction, let us consider some of
- the issues raised by the rational-number example. We defined the
- rational-number operations in terms of a constructor
- <tt>make-rat</tt> and selectors <tt>numer</tt> and
- <tt>denom</tt>. In general, the underlying idea of data
- abstraction is to identify for each type of data object a basic
- set of operations in terms of which all manipulations of data
- objects of that type will be expressed, and then to use only
- those operations in manipulating the data.</p>
-
- <p>We can envision the structure of the rational-number system as
- shown in figure&nbsp;<a href="#%_fig_2.1">2.1</a>. The horizontal
- lines represent <em>abstraction barriers</em> that isolate
- different ``levels'' of the system. At each level, the barrier
- separates the programs (above) that use the data abstraction from
- the programs (below) that implement the data abstraction.
- Programs that use rational numbers manipulate them solely in
- terms of the procedures supplied ``for public use'' by the
- rational-number package: <tt>add-rat</tt>, <tt>sub-rat</tt>,
- <tt>mul-rat</tt>, <tt>div-rat</tt>, and <tt>equal-rat?</tt>.
- These, in turn, are implemented solely in terms of the <a name="%_idx_1382"></a><a name="%_idx_1384"></a>constructor and
- selectors <tt>make-rat</tt>, <tt>numer</tt>, and <tt>denom</tt>,
- which themselves are implemented in terms of pairs. The details
- of how pairs are implemented are irrelevant to the rest of the
- rational-number package so long as pairs can be manipulated by
- the use of <tt>cons</tt>, <tt>car</tt>, and <tt>cdr</tt>. In
- effect, procedures at each level are the interfaces that define
- the abstraction barriers and connect the different levels.</p>
-
- <p><a name="%_fig_2.1"></a></p>
-
- <div align="left">
<div align="left">
- <b>Figure 2.1:</b>&nbsp;&nbsp;Data-abstraction barriers in
- the rational-number package.
+ <img src="ch2-Z-G-7.gif" border="0" />
</div>
- <table width="100%">
- <tr>
- <td>
- <div align="left">
- <img src="ch2-Z-G-6.gif" border="0" />&nbsp;
- </div>
- </td>
- </tr>
-
- <tr>
- <td></td>
- </tr>
- </table>
- </div>
-
- <p>This simple idea has many advantages. One advantage is that it
- makes programs much easier to maintain and to modify. Any complex
- data structure can be represented in a variety of ways with the
- primitive data structures provided by a programming language. Of
- course, the choice of representation influences the programs that
- operate on it; thus, if the representation were to be changed at
- some later time, all such programs might have to be modified
- accordingly. This task could be time-consuming and expensive in
- the case of large programs unless the dependence on the
- representation were to be confined by design to a very few
- program modules.</p>
-
- <p><a name="%_idx_1386"></a><a name="%_idx_1388"></a>For example,
- an alternate way to address the problem of reducing rational
- numbers to lowest terms is to perform the reduction whenever we
- access the parts of a rational number, rather than when we
- construct it. This leads to different constructor and selector
- procedures:</p>
-
- <p><tt><a name="%_idx_1390"></a>(define&nbsp;(make-rat&nbsp;n&nbsp;d)<br />
- &nbsp;&nbsp;(cons&nbsp;n&nbsp;d))<br />
- <a name="%_idx_1392"></a>(define&nbsp;(numer&nbsp;x)<br />
- &nbsp;&nbsp;(let&nbsp;((g&nbsp;(gcd&nbsp;(car&nbsp;x)&nbsp;(cdr&nbsp;x))))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;(/&nbsp;(car&nbsp;x)&nbsp;g)))<br />
- <a name="%_idx_1394"></a>(define&nbsp;(denom&nbsp;x)<br />
- &nbsp;&nbsp;(let&nbsp;((g&nbsp;(gcd&nbsp;(car&nbsp;x)&nbsp;(cdr&nbsp;x))))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;(/&nbsp;(cdr&nbsp;x)&nbsp;g)))<br /></tt></p>
-
- <p>The difference between this implementation and the previous
- one lies in when we compute the <tt>gcd</tt>. If in our typical
- use of rational numbers we access the numerators and denominators
- of the same rational numbers many times, it would be preferable
- to compute the <tt>gcd</tt> when the rational numbers are
- constructed. If not, we may be better off waiting until access
- time to compute the <tt>gcd</tt>. In any case, when we change
- from one representation to the other, the procedures
- <tt>add-rat</tt>, <tt>sub-rat</tt>, and so on do not have to be
- modified at all.</p>
-
- <p>Constraining the dependence on the representation to a few
- interface procedures helps us design programs as well as modify
- them, because it allows us to maintain the flexibility to
- consider alternate implementations. To continue with our simple
- example, suppose we are designing a rational-number package and
- we can't decide initially whether to perform the <tt>gcd</tt> at
- construction time or at selection time. The data-abstraction
- methodology gives us a way to defer that decision without losing
- the ability to make progress on the rest of the system.</p>
-
- <p><a name="%_thm_2.2"></a> <b>Exercise
- 2.2.</b>&nbsp;&nbsp;Consider the problem of representing <a name="%_idx_1396"></a>line segments in a plane. Each segment is
- represented as a pair of points: a starting point and an ending
- point. Define a constructor <a name="%_idx_1398"></a><tt>make-segment</tt> and selectors <a name="%_idx_1400"></a><tt>start-segment</tt> and <a name="%_idx_1402"></a><tt>end-segment</tt> that define the
- representation of segments in terms of points. Furthermore, a
- point <a name="%_idx_1404"></a>can be represented as a pair of
- numbers: the <em>x</em> coordinate and the <em>y</em> coordinate.
- Accordingly, specify a constructor <a name="%_idx_1406"></a><tt>make-point</tt> and selectors
- <tt>x-point</tt> and <tt>y-point</tt> that define this
- representation. Finally, using your selectors and constructors,
- define a procedure <a name="%_idx_1408"></a><tt>midpoint-segment</tt> that takes a line
- segment as argument and returns its midpoint (the point whose
- coordinates are the average of the coordinates of the endpoints).
- To try your procedures, you'll need a way to print points:</p>
-
- <p><tt><a name="%_idx_1410"></a>(define&nbsp;(print-point&nbsp;p)<br />
- &nbsp;&nbsp;(newline)<br />
- &nbsp;&nbsp;(display&nbsp;"(")<br />
- &nbsp;&nbsp;(display&nbsp;(x-point&nbsp;p))<br />
- &nbsp;&nbsp;(display&nbsp;",")<br />
- &nbsp;&nbsp;(display&nbsp;(y-point&nbsp;p))<br />
- &nbsp;&nbsp;(display&nbsp;")"))<br /></tt></p>
-
- <p><a name="%_thm_2.3"></a> <b>Exercise
- 2.3.</b>&nbsp;&nbsp;<a name="%_idx_1412"></a>Implement a
- representation for rectangles in a plane. (Hint: You may want to
- make use of exercise&nbsp;<a href="#%_thm_2.2">2.2</a>.) In terms
- of your constructors and selectors, create procedures that
- compute the perimeter and the area of a given rectangle. Now
- implement a different representation for rectangles. Can you
- design your system with suitable abstraction barriers, so that
- the same perimeter and area procedures will work using either
- representation?</p>
-
- <p><a name="%_sec_2.1.3"></a></p>
-
- <h3><a href="book-Z-H-4.html#%_toc_%_sec_2.1.3">2.1.3&nbsp;&nbsp;What Is
- Meant by Data?</a></h3>
-
- <p><a name="%_idx_1414"></a> We began the rational-number
- implementation in section&nbsp;<a href="#%_sec_2.1.1">2.1.1</a>
- by implementing the rational-number operations <tt>add-rat</tt>,
- <tt>sub-rat</tt>, and so on in terms of three unspecified
- procedures: <tt>make-rat</tt>, <tt>numer</tt>, and
- <tt>denom</tt>. At that point, we could think of the operations
- as being defined in terms of data objects -- numerators,
- denominators, and rational numbers -- whose behavior was
- specified by the latter three procedures.</p>
-
- <p>But exactly what is meant by <em>data</em>? It is not enough
- to say ``whatever is implemented by the given selectors and
- constructors.'' Clearly, not every arbitrary set of three
- procedures can serve as an appropriate basis for the
- rational-number implementation. We need to guarantee that,
- <a name="%_idx_1416"></a><a name="%_idx_1418"></a><a name="%_idx_1420"></a>if we construct a rational number <tt>x</tt>
- from a pair of integers <tt>n</tt> and <tt>d</tt>, then
- extracting the <tt>numer</tt> and the <tt>denom</tt> of
- <tt>x</tt> and dividing them should yield the same result as
- dividing <tt>n</tt> by <tt>d</tt>. In other words,
- <tt>make-rat</tt>, <tt>numer</tt>, and <tt>denom</tt> must
- satisfy the condition that, for any integer <tt>n</tt> and any
- non-zero integer <tt>d</tt>, if <tt>x</tt> is (<tt>make-rat n
- d</tt>), then</p>
-
- <div align="left"><img src="ch2-Z-G-7.gif" border="0" /></div>
-
- <p>In fact, this is the only condition <tt>make-rat</tt>,
- <tt>numer</tt>, and <tt>denom</tt> must fulfill in order to form
- a suitable basis for a rational-number representation. In
- general, we can think of data as defined by some collection of
- selectors and constructors, together with specified conditions
- that these procedures must fulfill in order to be a valid
- representation.<a href="#footnote_Temp_140" name="call_footnote_Temp_140" id="call_footnote_Temp_140"><sup><small>5</small></sup></a></p>
-
- <p><a name="%_idx_1446"></a><a name="%_idx_1448"></a>This point
- of view can serve to define not only ``high-level'' data objects,
- such as rational numbers, but lower-level objects as well.
- <a name="%_idx_1450"></a>Consider the notion of a pair, which we
- used in order to define our rational numbers. We never actually
- said what a pair was, only that the language supplied procedures
- <tt>cons</tt>, <tt>car</tt>, and <tt>cdr</tt> for operating on
- pairs. But the only thing we need to know about these three
- operations <a name="%_idx_1452"></a><a name="%_idx_1454"></a><a name="%_idx_1456"></a><a name="%_idx_1458"></a>is that if we glue two objects together using
- <tt>cons</tt> we can retrieve the objects using <tt>car</tt> and
- <tt>cdr</tt>. That is, the operations satisfy the condition that,
- for any objects <tt>x</tt> and <tt>y</tt>, if <tt>z</tt> is
- <tt>(cons x y)</tt> then <tt>(car z)</tt> is <tt>x</tt> and
- <tt>(cdr z)</tt> is <tt>y</tt>. Indeed, we mentioned that these
- three procedures are included as primitives in our language.
- However, any triple of procedures that satisfies the above
- condition can be used as the basis for implementing pairs. This
- point is illustrated strikingly by the fact that we could
- implement <tt>cons</tt>, <tt>car</tt>, and <tt>cdr</tt> without
- using any data structures at all but only using procedures. Here
- are the definitions:</p>
-
- <p><tt><a name="%_idx_1460"></a>(define&nbsp;(cons&nbsp;x&nbsp;y)<br />
- &nbsp;&nbsp;(define&nbsp;(dispatch&nbsp;m)<br />
- &nbsp;&nbsp;&nbsp;&nbsp;(cond&nbsp;((=&nbsp;m&nbsp;0)&nbsp;x)<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((=&nbsp;m&nbsp;1)&nbsp;y)<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(else&nbsp;(error&nbsp;"Argument&nbsp;not&nbsp;0&nbsp;or&nbsp;1&nbsp;--&nbsp;CONS"&nbsp;m))))<br />
-
- &nbsp;&nbsp;dispatch)<br />
- <br />
- <a name="%_idx_1462"></a>(define&nbsp;(car&nbsp;z)&nbsp;(z&nbsp;0))<br />
- <br />
- <a name="%_idx_1464"></a>(define&nbsp;(cdr&nbsp;z)&nbsp;(z&nbsp;1))<br /></tt></p>
-
- <p>This use of procedures corresponds to nothing like our
- intuitive notion of what data should be. Nevertheless, all we
- need to do to show that this is a valid way to represent pairs is
- to verify that these procedures satisfy the condition given
- above.</p>
-
- <p>The subtle point to notice is that the value returned by
- <tt>(cons x y)</tt> is a procedure -- namely the internally
- defined procedure <tt>dispatch</tt>, which takes one argument and
- returns either <tt>x</tt> or <tt>y</tt> depending on whether the
- argument is 0 or 1. Correspondingly, <tt>(car z)</tt> is defined
- to apply <tt>z</tt> to 0. Hence, if <tt>z</tt> is the procedure
- formed by <tt>(cons x y)</tt>, then <tt>z</tt> applied to 0 will
- yield <tt>x</tt>. Thus, we have shown that <tt>(car (cons x
- y))</tt> yields <tt>x</tt>, as desired. Similarly, <tt>(cdr (cons
- x y))</tt> applies the procedure returned by <tt>(cons x y)</tt>
- to 1, which returns <tt>y</tt>. Therefore, this procedural
- implementation of pairs is a valid implementation, and if we
- access pairs using only <tt>cons</tt>, <tt>car</tt>, and
- <tt>cdr</tt> we cannot distinguish this implementation from one
- that uses ``real'' data structures.</p>
-
- <p>The point of exhibiting the procedural representation of pairs
- is not that our language works this way (Scheme, and Lisp systems
- in general, implement pairs directly, for efficiency reasons) but
- that it could work this way. The procedural representation,
- although obscure, is a perfectly adequate way to represent pairs,
- since it fulfills the only conditions that pairs need to fulfill.
- This example also demonstrates that the ability to manipulate
- procedures as objects automatically provides the ability to
- represent compound data. This may seem a curiosity now, but
- procedural representations of data will play a central role in
- our programming repertoire. This style of programming is often
- called <a name="%_idx_1466"></a><em>message passing</em>, and we
- will be using it as a basic tool in chapter&nbsp;3 when we
- address the issues of modeling and simulation.</p>
-
- <p><a name="%_thm_2.4"></a> <b>Exercise 2.4.</b>&nbsp;&nbsp;Here
- is an alternative procedural representation of pairs. For this
- representation, verify that <tt>(car (cons x y))</tt> yields
- <tt>x</tt> for any objects <tt>x</tt> and <tt>y</tt>.</p>
-
- <p><tt><a name="%_idx_1468"></a>(define&nbsp;(cons&nbsp;x&nbsp;y)<br />
- &nbsp;&nbsp;(lambda&nbsp;(m)&nbsp;(m&nbsp;x&nbsp;y)))<br />
- <br />
- <a name="%_idx_1470"></a>(define&nbsp;(car&nbsp;z)<br />
- &nbsp;&nbsp;(z&nbsp;(lambda&nbsp;(p&nbsp;q)&nbsp;p)))<br /></tt></p>
-
- <p><a name="%_idx_1472"></a>What is the corresponding definition
- of <tt>cdr</tt>? (Hint: To verify that this works, make use of
- the substitution model of section&nbsp;<a href="book-Z-H-10.html#%_sec_1.1.5">1.1.5</a>.)</p>
-
- <p><a name="%_thm_2.5"></a> <b>Exercise 2.5.</b>&nbsp;&nbsp;Show
- that we can represent pairs of nonnegative integers using only
- numbers and arithmetic operations if we represent the pair
- <em>a</em> and <em>b</em> as the integer that is the product
- 2<sup><em>a</em></sup> 3<sup><em>b</em></sup>. Give the
- corresponding definitions of the procedures <tt>cons</tt>,
- <tt>car</tt>, and <tt>cdr</tt>.</p>
-
- <p><a name="%_thm_2.6"></a> <b>Exercise 2.6.</b>&nbsp;&nbsp;In
- case representing pairs as procedures wasn't mind-boggling
- enough, consider that, in a language that can manipulate
- procedures, we can get by without numbers (at least insofar as
- nonnegative integers are concerned) by implementing 0 and the
- operation of adding 1 as</p>
-
- <p>
- <tt>(define&nbsp;zero&nbsp;(lambda&nbsp;(f)&nbsp;(lambda&nbsp;(x)&nbsp;x)))<br />
-
- <br />
- (define&nbsp;(add-1&nbsp;n)<br />
- &nbsp;&nbsp;(lambda&nbsp;(f)&nbsp;(lambda&nbsp;(x)&nbsp;(f&nbsp;((n&nbsp;f)&nbsp;x)))))<br />
- </tt></p>
-
- <p>This representation is known as <a name="%_idx_1474"></a><em>Church numerals</em>, after its inventor,
- <a name="%_idx_1476"></a>Alonzo Church, the logician who invented
- the <img src="book-Z-G-D-6.gif" border="0" /> calculus.</p>
-
- <p>Define <tt>one</tt> and <tt>two</tt> directly (not in terms of
- <tt>zero</tt> and <tt>add-1</tt>). (Hint: Use substitution to
- evaluate <tt>(add-1 zero)</tt>). Give a direct definition of the
- addition procedure <tt>+</tt> (not in terms of repeated
- application of <tt>add-1</tt>).</p>
-
- <p><a name="%_sec_2.1.4"></a></p>
-
- <h3><a href="book-Z-H-4.html#%_toc_%_sec_2.1.4">2.1.4&nbsp;&nbsp;Extended
- Exercise: Interval Arithmetic</a></h3>
-
- <p><a name="%_idx_1478"></a><a name="%_idx_1480"></a> Alyssa P.
- Hacker is designing a system to help people solve engineering
- problems. One feature she wants to provide in her system is the
- ability to manipulate inexact quantities (such as measured
- parameters of physical devices) with known precision, so that
- when computations are done with such approximate quantities the
- results will be numbers of known precision.</p>
-
- <p>Electrical engineers will be using Alyssa's system to compute
- electrical quantities. It is sometimes necessary for them to
- compute the value of a parallel equivalent resistance
- <em>R</em><sub><em>p</em></sub> of two resistors
- <em>R</em><sub>1</sub> and <em>R</em><sub>2</sub> using the
- formula <a name="%_idx_1482"></a></p>
-
- <div align="left"><img src="ch2-Z-G-8.gif" border="0" /></div>
-
- <p>Resistance values are usually known only up to some <a name="%_idx_1484"></a>tolerance guaranteed by the manufacturer of the
- resistor. For example, if you buy a resistor labeled ``6.8 ohms
- with 10% tolerance'' you can only be sure that the resistor has a
- resistance between 6.8 - 0.68 = 6.12 and 6.8 + 0.68 = 7.48 ohms.
- Thus, if you have a 6.8-ohm 10% resistor in parallel with a
- 4.7-ohm 5% resistor, the resistance of the combination can range
- from about 2.58 ohms (if the two resistors are at the lower
- bounds) to about 2.97 ohms (if the two resistors are at the upper
- bounds).</p>
-
- <p>Alyssa's idea is to implement ``interval arithmetic'' as a set
- of arithmetic operations for combining ``intervals'' (objects
- that represent the range of possible values of an inexact
- quantity). The result of adding, subtracting, multiplying, or
- dividing two intervals is itself an interval, representing the
- range of the result.</p>
-
- <p>Alyssa postulates the existence of an abstract object called
- an ``interval'' that has two endpoints: a lower bound and an
- upper bound. She also presumes that, given the endpoints of an
- interval, she can construct the interval using the data
- constructor <a name="%_idx_1486"></a><tt>make-interval</tt>.
- Alyssa first writes a procedure for adding two intervals. She
- reasons that the minimum value the sum could be is the sum of the
- two lower bounds and the maximum value it could be is the sum of
- the two upper bounds:</p>
-
- <p><tt><a name="%_idx_1488"></a>(define&nbsp;(add-interval&nbsp;x&nbsp;y)<br />
- &nbsp;&nbsp;(make-interval&nbsp;(+&nbsp;(lower-bound&nbsp;x)&nbsp;(lower-bound&nbsp;y))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(+&nbsp;(upper-bound&nbsp;x)&nbsp;(upper-bound&nbsp;y))))<br />
- </tt></p>
-
- <p>Alyssa also works out the product of two intervals by finding
- the minimum and the maximum of the products of the bounds and
- using them as the bounds of the resulting interval. (<tt>Min</tt>
- and <tt>max</tt> are <a name="%_idx_1490"></a><a name="%_idx_1492"></a><a name="%_idx_1494"></a><a name="%_idx_1496"></a>primitives that find the minimum or maximum of
- any number of arguments.)</p>
-
- <p><tt><a name="%_idx_1498"></a>(define&nbsp;(mul-interval&nbsp;x&nbsp;y)<br />
- &nbsp;&nbsp;(let&nbsp;((p1&nbsp;(*&nbsp;(lower-bound&nbsp;x)&nbsp;(lower-bound&nbsp;y)))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(p2&nbsp;(*&nbsp;(lower-bound&nbsp;x)&nbsp;(upper-bound&nbsp;y)))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(p3&nbsp;(*&nbsp;(upper-bound&nbsp;x)&nbsp;(lower-bound&nbsp;y)))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(p4&nbsp;(*&nbsp;(upper-bound&nbsp;x)&nbsp;(upper-bound&nbsp;y))))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;(make-interval&nbsp;(min&nbsp;p1&nbsp;p2&nbsp;p3&nbsp;p4)<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(max&nbsp;p1&nbsp;p2&nbsp;p3&nbsp;p4))))<br />
- </tt></p>
-
- <p>To divide two intervals, Alyssa multiplies the first by the
- reciprocal of the second. Note that the bounds of the reciprocal
- interval are the reciprocal of the upper bound and the reciprocal
- of the lower bound, in that order.</p>
-
- <p><tt><a name="%_idx_1500"></a>(define&nbsp;(div-interval&nbsp;x&nbsp;y)<br />
- &nbsp;&nbsp;(mul-interval&nbsp;x&nbsp;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(make-interval&nbsp;(/&nbsp;1.0&nbsp;(upper-bound&nbsp;y))<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(/&nbsp;1.0&nbsp;(lower-bound&nbsp;y)))))<br />
- </tt></p>
-
- <p><a name="%_thm_2.7"></a> <b>Exercise
- 2.7.</b>&nbsp;&nbsp;Alyssa's program is incomplete because she
- has not specified the implementation of the interval abstraction.
- Here is a definition of the interval constructor:</p>
-
- <p><tt><a name="%_idx_1502"></a>(define&nbsp;(make-interval&nbsp;a&nbsp;b)&nbsp;(cons&nbsp;a&nbsp;b))<br />
- </tt></p>
-
- <p>Define selectors <a name="%_idx_1504"></a><tt>upper-bound</tt>
- and <a name="%_idx_1506"></a><tt>lower-bound</tt> to complete the
- implementation.</p>
-
- <p><a name="%_thm_2.8"></a> <b>Exercise 2.8.</b>&nbsp;&nbsp;Using
- reasoning analogous to Alyssa's, describe how the difference of
- two intervals may be computed. Define a corresponding subtraction
- procedure, called <a name="%_idx_1508"></a><tt>sub-interval</tt>.</p>
-
- <p><a name="%_thm_2.9"></a> <b>Exercise
- 2.9.</b>&nbsp;&nbsp;<a name="%_idx_1510"></a>The <em>width</em>
- of an interval is half of the difference between its upper and
- lower bounds. The width is a measure of the uncertainty of the
- number specified by the interval. For some arithmetic operations
- the width of the result of combining two intervals is a function
- only of the widths of the argument intervals, whereas for others
- the width of the combination is not a function of the widths of
- the argument intervals. Show that the width of the sum (or
- difference) of two intervals is a function only of the widths of
- the intervals being added (or subtracted). Give examples to show
- that this is not true for multiplication or division.</p>
-
- <p><a name="%_thm_2.10"></a> <b>Exercise
- 2.10.</b>&nbsp;&nbsp;<a name="%_idx_1512"></a>Ben Bitdiddle, an
- expert systems programmer, looks over Alyssa's shoulder and
- comments that it is not clear what it means to divide by an
- interval that spans zero. Modify Alyssa's code to check for this
- condition and to signal an error if it occurs.</p>
-
- <p><a name="%_thm_2.11"></a> <b>Exercise
- 2.11.</b>&nbsp;&nbsp;<a name="%_idx_1514"></a>In passing, Ben
- also cryptically comments: ``By testing the signs of the
- endpoints of the intervals, it is possible to break
- <tt>mul-interval</tt> into nine cases, only one of which requires
- more than two multiplications.'' Rewrite this procedure using
- Ben's suggestion.</p>
-
- <p>After debugging her program, Alyssa shows it to a potential
- user, who complains that her program solves the wrong problem. He
- wants a program that can deal with numbers represented as a
- center value and an additive tolerance; for example, he wants to
- work with intervals such as 3.5&plusmn; 0.15 rather than [3.35,
- 3.65]. Alyssa returns to her desk and fixes this problem by
- supplying an alternate constructor and alternate selectors:</p>
-
- <p><tt><a name="%_idx_1516"></a>(define&nbsp;(make-center-width&nbsp;c&nbsp;w)<br />
-
- &nbsp;&nbsp;(make-interval&nbsp;(-&nbsp;c&nbsp;w)&nbsp;(+&nbsp;c&nbsp;w)))<br />
-
- <a name="%_idx_1518"></a>(define&nbsp;(center&nbsp;i)<br />
- &nbsp;&nbsp;(/&nbsp;(+&nbsp;(lower-bound&nbsp;i)&nbsp;(upper-bound&nbsp;i))&nbsp;2))<br />
-
- <a name="%_idx_1520"></a>(define&nbsp;(width&nbsp;i)<br />
- &nbsp;&nbsp;(/&nbsp;(-&nbsp;(upper-bound&nbsp;i)&nbsp;(lower-bound&nbsp;i))&nbsp;2))<br />
- </tt></p>
-
- <p>Unfortunately, most of Alyssa's users are engineers. Real
- engineering situations usually involve measurements with only a
- small uncertainty, measured as the ratio of the width of the
- interval to the midpoint of the interval. Engineers usually
- specify percentage tolerances on the parameters of devices, as in
- the resistor specifications given earlier.</p>
-
- <p><a name="%_thm_2.12"></a> <b>Exercise
- 2.12.</b>&nbsp;&nbsp;Define a constructor <a name="%_idx_1522"></a><tt>make-center-percent</tt> that takes a center
- and a percentage tolerance and produces the desired interval. You
- must also define a selector <tt>percent</tt> that produces the
- percentage tolerance for a given interval. The <tt>center</tt>
- selector is the same as the one shown above.</p>
-
- <p><a name="%_thm_2.13"></a> <b>Exercise
- 2.13.</b>&nbsp;&nbsp;Show that under the assumption of small
- percentage tolerances there is a simple formula for the
- approximate percentage tolerance of the product of two intervals
- in terms of the tolerances of the factors. You may simplify the
- problem by assuming that all numbers are positive.</p>
-
- <p>After considerable work, Alyssa P. Hacker delivers her
- finished system. Several years later, after she has forgotten all
- about it, she gets a frenzied call from an irate user, Lem E.
- Tweakit. It seems that Lem has noticed that the formula for
- parallel resistors can be written in two <a name="%_idx_1524"></a>algebraically equivalent ways:</p>
-
- <div align="left"><img src="ch2-Z-G-9.gif" border="0" /></div>
-
- <p>and</p>
-
- <div align="left"><img src="ch2-Z-G-10.gif" border="0" /></div>
-
- <p>He has written the following two programs, each of which
- computes the parallel-resistors formula differently:</p>
-
- <p><tt>(define&nbsp;(par1&nbsp;r1&nbsp;r2)<br />
- &nbsp;&nbsp;(div-interval&nbsp;(mul-interval&nbsp;r1&nbsp;r2)<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(add-interval&nbsp;r1&nbsp;r2)))<br />
-
- (define&nbsp;(par2&nbsp;r1&nbsp;r2)<br />
- &nbsp;&nbsp;(let&nbsp;((one&nbsp;(make-interval&nbsp;1&nbsp;1)))&nbsp;<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;(div-interval&nbsp;one<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(add-interval&nbsp;(div-interval&nbsp;one&nbsp;r1)<br />
-
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(div-interval&nbsp;one&nbsp;r2)))))<br />
- </tt></p>
-
- <p>Lem complains that Alyssa's program gives different answers
- for the two ways of computing. This is a serious complaint.</p>
-
- <p><a name="%_thm_2.14"></a> <b>Exercise
- 2.14.</b>&nbsp;&nbsp;Demonstrate that Lem is right. Investigate
- the behavior of the system on a variety of arithmetic
- expressions. Make some intervals <em>A</em> and <em>B</em>, and
- use them in computing the expressions <em>A</em>/<em>A</em> and
- <em>A</em>/<em>B</em>. You will get the most insight by using
- intervals whose width is a small percentage of the center value.
- Examine the results of the computation in center-percent form
- (see exercise&nbsp;<a href="#%_thm_2.12">2.12</a>).</p>
-
- <p><a name="%_thm_2.15"></a> <b>Exercise 2.15.</b>&nbsp;&nbsp;Eva
- Lu Ator, another user, has also noticed the different intervals
- computed by different but algebraically equivalent expressions.
- She says that a formula to compute with intervals using Alyssa's
- system will produce tighter error bounds if it can be written in
- such a form that no variable that represents an uncertain number
- is repeated. Thus, she says, <tt>par2</tt> is a ``better''
- program for parallel resistances than <tt>par1</tt>. Is she
- right? Why?</p>
-
- <p><a name="%_thm_2.16"></a> <b>Exercise
- 2.16.</b>&nbsp;&nbsp;Explain, in general, why equivalent
- algebraic expressions may lead to different answers. Can you
- devise an interval-arithmetic package that does not have this
- shortcoming, or is this task impossible? (Warning: This problem
- is very difficult.)</p>
-
- <div class="smallprint">
- <hr />
- </div>
-
- <div class="footnote">
- <p><a href="#call_footnote_Temp_133" name="footnote_Temp_133" id="footnote_Temp_133"><sup><small>2</small></sup></a> The name
- <a name="%_idx_1332"></a><tt>cons</tt> stands for
- ``construct.'' The names <a name="%_idx_1334"></a><tt>car</tt>
- and <a name="%_idx_1336"></a><tt>cdr</tt> derive from the
- original implementation of Lisp on the <a name="%_idx_1338"></a><a name="%_idx_1340"></a>IBM 704. That machine
- had an addressing scheme that allowed one to reference the
- ``address'' and ``decrement'' parts of a memory location.
- <tt>Car</tt> stands for ``Contents of Address part of
- Register'' and <tt>cdr</tt> (pronounced ``could-er'') stands
- for ``Contents of Decrement part of Register.''</p>
-
- <p><a href="#call_footnote_Temp_135" name="footnote_Temp_135" id="footnote_Temp_135"><sup><small>3</small></sup></a> Another
- way to define the selectors and constructor is</p>
-
- <p><tt>(define&nbsp;make-rat&nbsp;cons)<br />
- (define&nbsp;numer&nbsp;car)<br />
- (define&nbsp;denom&nbsp;cdr)<br /></tt></p>
-
- <p>The first definition associates the name <tt>make-rat</tt>
- with the value of the expression <tt>cons</tt>, which is the
- primitive procedure that constructs pairs. Thus
- <tt>make-rat</tt> and <tt>cons</tt> are names for the same
- primitive constructor.</p>
-
- <p>Defining selectors and constructors in this way is
- efficient: Instead of <tt>make-rat</tt> <em>calling</em>
- <tt>cons</tt>, <tt>make-rat</tt> <em>is</em> <tt>cons</tt>, so
- there is only one procedure called, not two, when
- <tt>make-rat</tt> is called. On the other hand, doing this
- defeats debugging aids that trace procedure calls or put
- breakpoints on procedure calls: You may want to watch
- <tt>make-rat</tt> being called, but you certainly don't want to
- watch every call to <tt>cons</tt>.</p>
-
- <p>We have chosen not to use this style of definition in this
- book.</p>
-
- <p><a href="#call_footnote_Temp_136" name="footnote_Temp_136" id="footnote_Temp_136"><sup><small>4</small></sup></a> <a name="%_idx_1356"></a><a name="%_idx_1358"></a><a name="%_idx_1360"></a><a name="%_idx_1362"></a><a name="%_idx_1364"></a><tt>Display</tt> is the Scheme primitive for
- printing data. The Scheme primitive <tt>newline</tt> starts a
- new line for printing. <a name="%_idx_1366"></a><a name="%_idx_1368"></a>Neither of these procedures returns a useful
- value, so in the uses of <tt>print-rat</tt> below, we show only
- what <tt>print-rat</tt> prints, not what the interpreter prints
- as the value returned by <tt>print-rat</tt>.</p>
-
- <p><a href="#call_footnote_Temp_140" name="footnote_Temp_140" id="footnote_Temp_140"><sup><small>5</small></sup></a>
- Surprisingly, this idea is very difficult to formulate
- rigorously. There are two approaches to giving such a
- formulation. One, pioneered by <a name="%_idx_1422"></a>C. A.
- R. Hoare (1972), is known as the method of <a name="%_idx_1424"></a><a name="%_idx_1426"></a><em>abstract
- models</em>. It formalizes the ``procedures plus conditions''
- specification as outlined in the rational-number example above.
- Note that the condition on the rational-number representation
- was stated in terms of facts about integers (equality and
- division). In general, abstract models define new kinds of data
- objects in terms of previously defined types of data objects.
- Assertions about data objects can therefore be checked by
- reducing them to assertions about previously defined data
- objects. Another approach, introduced by <a name="%_idx_1428"></a>Zilles at MIT, by <a name="%_idx_1430"></a>Goguen, <a name="%_idx_1432"></a>Thatcher,