diff options
author | elioat <elioat@tilde.institute> | 2023-08-23 07:52:19 -0400 |
---|---|---|
committer | elioat <elioat@tilde.institute> | 2023-08-23 07:52:19 -0400 |
commit | 562a9a52d599d9a05f871404050968a5fd282640 (patch) | |
tree | 7d3305c1252c043bfe246ccc7deff0056aa6b5ab /js/games/nluqo.github.io/~bh/ssch4/defining.html | |
parent | 5d012c6c011a9dedf7d0a098e456206244eb5a0f (diff) | |
download | tour-562a9a52d599d9a05f871404050968a5fd282640.tar.gz |
*
Diffstat (limited to 'js/games/nluqo.github.io/~bh/ssch4/defining.html')
-rw-r--r-- | js/games/nluqo.github.io/~bh/ssch4/defining.html | 754 |
1 files changed, 754 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/ssch4/defining.html b/js/games/nluqo.github.io/~bh/ssch4/defining.html new file mode 100644 index 0000000..4dbef0b --- /dev/null +++ b/js/games/nluqo.github.io/~bh/ssch4/defining.html @@ -0,0 +1,754 @@ +<P> +<A NAME="plugboard"></A> +<P> +<CENTER><IMG SRC="../ss-pics/plugboard.jpg" ALT="figure: plugboard"></CENTER><P><CENTER>In the old days, they "defined procedures" like this. +</CENTER><P> + +<HTML> +<HEAD> +<TITLE>Simply Scheme: Introducing Computer Science ch 4: Defining Your Own Procedures</TITLE> +</HEAD> +<BODY> +<HR> +<CITE>Simply Scheme:</CITE> +<CITE>Introducing Computer Science</CITE> 2/e Copyright (C) 1999 MIT +<H2>Chapter 4</H2> +<H1>Defining Your Own Procedures</H1> + +<TABLE width="100%"><TR><TD> +<IMG SRC="../simply.jpg" ALT="cover photo"> +<TD><TABLE> +<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian +Harvey</A><BR>University of California, Berkeley</CITE> +<TR><TD align="right"><CITE><A HREF="http://ccrma.stanford.edu/~matt">Matthew +Wright</A><BR>University of California, Santa Barbara</CITE> +<TR><TD align="right"><BR> +<TR><TD align="right"><A HREF="../pdf/ssch04.pdf">Download PDF version</A> +<TR><TD align="right"><A HREF="../ss-toc2.html">Back to Table of Contents</A> +<TR><TD align="right"><A HREF="../ssch3/people.html"><STRONG>BACK</STRONG></A> +chapter thread <A HREF="../ssch5/words.html"><STRONG>NEXT</STRONG></A> +<TR><TD align="right"><A HREF="http://mitpress.mit.edu/0262082810">MIT +Press web page for <CITE>Simply Scheme</CITE></A> +</TABLE></TABLE> + +<HR> + + +<P>Until now we've been using procedures that Scheme already knows when you +begin working with it. In this chapter you'll find out how to create +new procedures. + +<P><H2>How to Define a Procedure</H2> + +<P>A Scheme program consists of one or more <EM>procedures.</EM> A procedure is +a description of the process by which a computer can work out some result +that we want. Here's how to define a procedure that returns the square of +its argument: + +<P><PRE>(define (<A NAME="g1"></A>square x) + (* x x)) +</PRE> + +<P>(The value returned by <A NAME="g2"></A><CODE>define</CODE> may differ depending on the +version of Scheme you're using. Many versions return the name of the +procedure you're defining, but others return something else. It doesn't +matter, because when you use <CODE>define</CODE> you aren't interested in the +returned value, but rather in the fact that Scheme remembers the new +definition for later use.) + +<P>This is the definition of a procedure called <CODE>square</CODE>. <CODE>Square</CODE> +takes one argument, a number, and it returns the square of that number. +Once you have defined <CODE>square</CODE>, you can use it just the same way as you +use primitive procedures: + +<P><PRE>> (square 7) +49 + +> (+ 10 (square 2)) +14 + +> (square (square 3)) +81 +</PRE> + +<P>This procedure definition has four parts. The first is the word <CODE>define</CODE>, which indicates that you are defining something. The second and +third come together inside parentheses: the name that you want to give the +procedure and the name(s) you want to use for its argument(s). This +arrangement was chosen by the designers of Scheme because it looks like the +form in which the procedure will be invoked. That is, <CODE>(square x)</CODE> looks +like <CODE>(square 7)</CODE>. The fourth part of the definition is the <EM>body:</EM> an expression whose value provides the function's return value. + +<P><CENTER><IMG SRC="../ss-pics/definition.jpg" ALT="figure: definition"></CENTER> + +<P><H2>Special Forms</H2> + +<P><CODE>Define</CODE> is a <EM><A NAME="g3"></A><A NAME="g4"></A>special form,</EM> an exception to the +evaluation rule we've been going on about.<A NAME="text1" HREF="defining.html#ft1">[1]</A> Usually, an expression represents a procedure invocation, so +the general rule is that Scheme first evaluates all the subexpressions, and +then applies the resulting procedure to the resulting argument values. The +specialness of special forms is that Scheme <EM>doesn't</EM> evaluate all the +subexpressions. Instead, each special form has its own particular +evaluation rule. For example, when we defined <CODE>square</CODE>, no +part of the definition was evaluated: not <CODE>square</CODE>, not <CODE>x</CODE>, and +not <CODE>(* x x)</CODE>. It wouldn't make sense to evaluate <CODE>(square x)</CODE> +because you can't invoke the <CODE>square</CODE> procedure before you define it! + +<P>It would be possible to describe special forms using the following model: +"Certain procedures want their arguments unevaluated, and Scheme recognizes +them. After refraining from evaluating <CODE>define</CODE>'s arguments, for +example, Scheme invokes the <CODE>define</CODE> procedure with those unevaluated +arguments." But in fact the designers of Scheme chose to think about it +differently. The entire special form that starts with <CODE>define</CODE> is just a +completely different kind of thing from a procedure call. In Scheme there +is no procedure named <CODE>define</CODE>. In fact, <CODE>define</CODE> is not the name +of anything at all: + +<P><PRE>> + +#<PRIMITIVE PROCEDURE +> + +> define +ERROR - INVALID CONTEXT FOR KEYWORD DEFINE +</PRE> + +<P>Nevertheless, in this book, unless it's really important to make +the distinction, we'll talk as if there were a procedure called <CODE>define</CODE>. +For example, we'll talk about "<CODE>define</CODE>'s arguments" and "the value +returned by <CODE>define</CODE>" and "invoking <CODE>define</CODE>." + +<P><H2>Functions and Procedures</H2> + +<P>Throughout most of this book, our procedures will describe processes that +<A NAME="g5"></A> +<A NAME="g6"></A> +compute <EM>functions.</EM> A function is a connection between some values +you already know and a new value you want to find out. For example, the +<EM>square</EM> function takes a number, such as 8, as its input value and +returns another number, 64 in this case, as its output value. The <EM>plural</EM> function takes a noun, such as "computer," and returns another +word, "computers" in this example. The technical term for the function's +input value is its <EM>argument.</EM> A function may take more than one +argument; for example, the <CODE>remainder</CODE> function takes two arguments, +such as 12 and 5. It returns one value, the remainder on dividing the first +argument by the second (in this case, 2). + +<P>We said earlier that a procedure is "a description of the process by which +a computer can work out some result that we want." What do we mean by <EM>process</EM>? Consider these two definitions: + +<P><P><P><CENTER><EM>f</EM>(<EM>x</EM>)=3<EM>x</EM>+12<BR> +<EM>g</EM>(<EM>x</EM>)=3(<EM>x</EM>+4)<P></CENTER> + +The two definitions call for different arithmetic operations. For +example, to compute <EM>f</EM>(8) we'd multiply 8 by 3, then add 12 to the result. +To compute <EM>g</EM>(8), we'd add 4 to 8, then multiply the result by 3. But we +get the same answer, 36, either way. These two equations describe different +<EM>processes,</EM> but they compute the same <EM>function.</EM> The function +is just the association between the starting value(s) and the resulting +value, no matter how that result is computed. In Scheme we could say + +<P><PRE>(define (f x) + (+ (* 3 x) 12)) + +(define (g x) + (* 3 (+ x 4))) +</PRE> + +<P>and we'd say that <CODE>f</CODE> and <CODE>g</CODE> are two procedures that +represent the same function. + +<P>In real life, functions are not always represented by procedures. We could +represent a function by a <EM>table</EM> showing all its possible values, +like this: + +<P><P><CENTER><TABLE><TR><TD>Alabama<TD> Montgomery +<TR><TD>Alaska<TD> Juneau +<TR><TD>Arizona<TD> Phoenix +<TR><TD>Arkansas<TD> Little Rock +<TR><TD>California<TD> Sacramento +<TR><TD>…<TD> …</TABLE></CENTER> + +This table represents the State Capital function; we haven't shown +all the lines of the complete table, but we could. There are only a finite +number of U.S. states. Numeric functions can also be represented by <EM>graphs,</EM> as you probably learned in high school algebra. In this book our +focus is on the representation of functions by procedures. The only reason +for showing you this table example is to clarify what we mean when we say +that a function <EM>is represented by</EM> a procedure, rather than that a +function <EM>is</EM> the procedure. + +<P>We'll say "the procedure <CODE>f</CODE>" when we want to discuss the operations +we're telling Scheme to carry out. We'll say "the function represented by +<CODE>f</CODE>" when our attention is focused on the value returned, rather than +on the mechanism. (But we'll often abbreviate that lengthy second phrase +with "the function <CODE>f</CODE>" unless the context is especially +confusing.)<A NAME="text2" HREF="defining.html#ft2">[2]</A> + +<P><H2>Argument Names versus Argument Values</H2> + +<P><P><A NAME="alice"></A> +<BLOCKQUOTE> + +<P>"It's long," said the Knight, "but it's very, <EM>very</EM> beautiful. +Everybody that hears me sing it—either it brings the <EM>tears</EM> into +their eyes, or else—" + +<P>"Or else what?" said Alice, for the Knight had made a sudden pause. + +<P>“Or else it doesn't, you know. The name of the song is called ‘<EM>Haddock's Eyes.</EM>’ ” + +<P>"Oh, that's the name of the song, is it?" Alice said, trying to feel +interested. + +<P>"No, you don't understand," the Knight said, looking a little vexed. +“That's what the name is <EM>called.</EM> The name really is ‘<EM>The Aged +Aged Man.</EM>&rsquo ” + +<P>“Then I ought to have said ‘That's what the <EM>song</EM> is called’?” +Alice corrected herself. + +<P>“No, you oughtn't; that's quite another thing! The <EM>song</EM> is called +&lsquo<EM>Ways And Means</EM>&rsquo: but that's only what it's <EM>called,</EM> you +know!” + +<P>"Well, what <EM>is</EM> the song, then?" said Alice, who was by this time +completely bewildered. + +<P>"I was coming to that," the Knight said. “The song really is &lsquo<EM>A-sitting On A Gate</EM>’: and the tune's my own invention.” + +<P><A NAME="g7"></A>Lewis Carroll, <EM>Through the Looking-Glass, and What +Alice Found There</EM> + +<P></BLOCKQUOTE><P> +Notice that when we <EM>defined</EM> the <CODE>square</CODE> procedure we gave a <EM>name,</EM> <CODE>x</CODE>, for its argument. By contrast, when we <EM>invoked</EM> +<CODE>square</CODE> we provided a <EM>value</EM> for the argument (e.g., <CODE>7</CODE>). +The word <CODE>x</CODE> is a "place holder" in the definition that stands for +whatever value you use when you call the procedure. So you can read the +definition of <CODE>square</CODE> as saying, "In order to <CODE>square</CODE> a number, +multiply <EM>that number</EM> by <EM>that number.</EM>" The name <CODE>x</CODE> +holds the place of the particular number that you mean. + +<P>Be sure you understand this distinction between defining a procedure and +calling it. A procedure represents a general technique that can be applied +to many specific cases. We don't want to build any particular case into the +procedure definition; we want the definition to express the general nature of +the technique. You wouldn't want a procedure that only knew how to take the +square of 7. But when you actually get around to using <CODE>square</CODE>, you have +to be specific about which number you're squaring. + +<P>The name for the name of an argument (whew!) is <EM><A NAME="g8"></A><A NAME="g9"></A>formal parameter.</EM> In our <CODE>square</CODE> example, <CODE>x</CODE> +is the formal parameter. (You may hear people say either "formal" +alone or "parameter" alone when they're feeling lazy.) The +technical term for the actual value of the argument is the <EM><A NAME="g10"></A><A NAME="g11"></A>actual argument.</EM> In a case like + +<P> +<PRE>(square (+ 5 9)) +</PRE> + + +<P> +you may want to distinguish the <EM><A NAME="g12"></A><A NAME="g13"></A>actual argument expression</EM> <CODE>(+ 5 9)</CODE> from the <EM><A NAME="g14"></A><A NAME="g15"></A>actual argument value</EM> 14. Most of the time it's perfectly clear +what you mean, and you just say "argument" for all of these things, but +right now when you're learning these ideas it's important to be able to talk +more precisely. + +<P> +The <CODE>square</CODE> procedure takes one argument. If a procedure requires more +than one argument, then the question arises, which actual argument goes with +which formal parameter? The answer is that they go in the order in which +you write them, like this: + +<P><PRE>(define (f a b) + (+ (* 3 a) b)) + +> (f 5 8) +23 + +> (f 8 5) +29 +</PRE> + +<P><H2>Procedure as Generalization</H2> +<A NAME="g16"></A> + +<P>What's the average of 17 and 25? To answer this question you could add the +two numbers, getting 42, and divide that by two, getting 21. You could ask +Scheme to do this for you: + +<P><PRE>> (/ (+ 17 25) 2) +21 +</PRE> + +<P>What's the average of 14 and 68? + +<P><PRE>> (/ (+ 14 68) 2) +41 +</PRE> + +<P>Once you understand the technique, you could answer any such question by +typing an expression of the form + +<P><PRE>(/ (+ ______ ______ ) 2) +</PRE> + +<P>to Scheme. + +<P>But if you're going to be faced with more such problems, an obvious next +step is to <EM>generalize</EM> the technique by defining a procedure: + +<P><PRE>(define (<A NAME="g17"></A>average a b) + (/ (+ a b) 2)) +</PRE> + +<P>With this definition, you can think about the next problem that +comes along in terms of the problem itself, rather than in terms of the +steps required for its solution: + +<P><PRE>> (average 27 4) +15.5 +</PRE> + +<P>This is an example of what we meant when we defined +"abstraction" as noticing a pattern and giving it a name. +It's not so different from the naming of such patterns in English; +when someone invented the name "average" it was, probably, after +noticing that it was often useful to find the value halfway between +two other values. + +<P>This naming process is more important than it sounds, because once we have a +name for some idea, we can use that idea without thinking about its pieces. +For example, suppose that you want to know not only the average of some +numbers but also a measure of whether the numbers are clumped together close +to the average, or widely spread out. Statisticians have developed the +"standard deviation" as a measure of this second property. You'd rather +not have to think about this mysterious formula: + +<P><P><CENTER><IMG SRC="math1.gif" ALT="math display"></CENTER><P> + +<P>but you'd be happy to use a procedure <CODE>standard-deviation</CODE> +that you found in a collection of statistical programs. + +<P>After all, there's no law of nature that says computers automatically know +how to add or subtract. You could imagine having to instruct Scheme to +compute the sum of two large numbers digit by digit, the way you did in +elementary school. But instead someone has "taught" your computer how to +add before you get to it, giving this technique the name <CODE>+</CODE> so that you +can ask for the sum of two numbers without thinking about the steps required. +By inventing <CODE>average</CODE> or <CODE>standard-deviation</CODE> we are extending the +repertoire of computations that you can ask for without concerning yourself +with the details. + +<P><H2>Composability</H2> + +<P>We've suggested that a procedure you define, such as <CODE>average</CODE>, is +<A NAME="g18"></A> +<A NAME="g19"></A> +essentially similar to one that's built into Scheme, such as <CODE>+</CODE>. +In particular, the rules for building expressions are the same whether +the building blocks are primitive procedures or defined procedures. + +<P><PRE>> (average (+ 10 8) (* 3 5)) +16.5 + +> (average (average 2 3) (average 4 5)) +3.5 + +> (sqrt (average 143 145)) +12 +</PRE> + +<P>Any return value can be used as an end in itself, as the return +value from <CODE>sqrt</CODE> was used in the last of these examples, or it can +provide an argument to another procedure, as the return value from +<CODE>*</CODE> was used in the first of these examples. + +<P>These small examples may seem arbitrary, but the same idea, composition of +functions, is the basis for all Scheme programming. For example, the +complicated formula we gave for standard deviation requires computing the +squares of several numbers. So if we were to write a <CODE>standard-deviation</CODE> procedure, it would invoke <CODE>square</CODE>. + +<P><H2>The Substitution Model</H2> + +<P>We've paid a lot of attention to the details of formal parameters and actual +arguments, but we've been a little handwavy<A NAME="text3" HREF="defining.html#ft3">[3]</A> about how a procedure actually computes a value when you invoke it. + +<P>We're going to explain what happens when you invoke a user-defined procedure. +Every explanation is a story. No story tells the entire truth, because there +are always some details left out. A <EM>model</EM> is a story that +has just enough detail to help you understand whatever it's trying to explain +but not so much detail that you can't see the forest for the trees. + +<P>Today's story is about the <EM>substitution</EM> model. When a +procedure is invoked, the goal is to carry out the computation described in +its body. The problem is that the body is written in terms of the formal +parameters, while the computation has to use the actual argument values. So +what Scheme needs is a way to associate actual argument values with formal +parameters. It does this by making a new copy of the body of the procedure, +in which it substitutes the argument values for every appearance of the +formal parameters, and then evaluating the resulting expression. So, if +you've defined <CODE>square</CODE> with + +<P><PRE>(define (square x) + (* x x)) +</PRE> + +<P>then the body of <CODE>square</CODE> is <CODE>(* x x)</CODE>. When you want to +know the square of a particular number, as in <CODE>(square 5)</CODE>, Scheme +substitutes the 5 for <CODE>x</CODE> everywhere in the body of square and evaluates +the expression. In other words, Scheme takes + +<P><PRE>(* x x) +</PRE> + +<P>then does the substitution, getting + +<P><PRE>(* 5 5) +</PRE> + +<P>and then evaluates that expression, getting 25. + +<P>If you just type <CODE>(* x x)</CODE> into Scheme, you will get an error message +complaining that <CODE>x</CODE> doesn't mean anything. Only after the substitution +does this become a meaningful expression. + +<P>By the way, when we talk about "substituting into the body," we don't mean +that the procedure's definition is changed in any permanent way. The body of +the procedure doesn't change; what happens, as we said before, is that Scheme +constructs a new expression that looks like the body, except for the +substitutions.<A NAME="text4" HREF="defining.html#ft4">[4]</A> + +<P>There are little people who specialize in <CODE>square</CODE>, just as there +are little people who specialize in <CODE>+</CODE> and <CODE>*</CODE>. The difference is +that the little people who do primitive procedures can do the work "in their +head," all at once. The little people who carry out user-defined procedures +have to go through this substitution business we're talking about here. +Then they hire other little people to help evaluate the resulting expression, +just as Alonzo hires people to help him evaluate the expressions you type +directly to Scheme. + +<P>Let's say Sam, a little person who specializes in <CODE>square</CODE>, has been +asked to compute <CODE>(square 6)</CODE>. Sam carries out the substitution, and is +left with the expression <CODE>(* 6 6)</CODE> to evaluate. Sam then hires Tessa, a +multiplication specialist, to evaluate this new expression. Tessa tells Sam +that her answer is 36, and, because the multiplication is the entire problem +to be solved, this is Sam's answer also. + +<P>Here's another example: + +<P><PRE>(define (<A NAME="g20"></A>hypotenuse a b) + (sqrt (+ (square a) (square b)))) + +> (hypotenuse 5 12) +</PRE> + +<P> Suppose Alonzo hires Harry to compute this expression. +Harry must first substitute the actual argument values (5 and 12) into the +body of <CODE>hypotenuse</CODE>: + +<P><PRE>(sqrt (+ (square 5) (square 12))) +</PRE> + +<P>Now he evaluates that expression, just as Alonzo would evaluate it +if you typed it at a Scheme prompt. That is, Harry hires four little +people: one <CODE>sqrt</CODE> expert, one <CODE>+</CODE> expert, and two <CODE>square</CODE> +experts.<A NAME="text5" HREF="defining.html#ft5">[5]</A> In particular, some little +person has to evaluate <CODE>(square 5)</CODE>, by substituting 5 for <CODE>x</CODE> in +the body of <CODE>square</CODE>, as in the earlier example. Similarly, we +substitute 12 for <CODE>x</CODE> in order to evaluate <CODE>(square 12)</CODE>: + +<P><PRE>(hypotenuse 5 12) ; substitute into HYPOTENUSE body +(sqrt (+ (square 5) (square 12))) ; substitute for (SQUARE 5) + (* 5 5) + 25 +(sqrt (+ 25 (square 12))) ; substitute for (SQUARE 12) + (* 12 12) + 144 +(sqrt (+ 25 144)) + (+ 25 144) ; combine the results as before + 169 +(sqrt 169) +13 +</PRE> + +<P>Don't forget, in the heady rush of learning about the substitution +model, what you already knew from before: Each piece of this computation is +done by a little person, and some other little person is waiting for the +result. In other words, the substitution model tells us how <EM>each +compound procedure</EM> is carried out, but doesn't change our picture of the +way in which procedure invocations are <EM>composed</EM> into larger +expressions. + +<P><H2>Pitfalls</H2> + +<P>Don't forget that a function can have only <EM>one</EM> return value. +For example, here's a program that's supposed to return the sum of the +squares of its two arguments: + +<P><PRE>(define (sum-of-squares x y) ;; wrong! + (square x) + (square y)) +</PRE> + +<P>The problem is that the body of this procedure has two expressions, +instead of just one. As it turns out, Scheme just ignores the value of the +first expression in cases like this, and returns the value of the last one. +What the programmer wants is the <EM>sum</EM> of these two values, so the +procedure should say + +<P><PRE>(define (sum-of-squares x y) + (+ (square x) + (square y))) +</PRE> + +<P>Another pitfall comes from thinking that a procedure call changes the +value of a parameter. Here's a faulty program that's supposed to compute +the function described by <EM>f</EM>(<EM>x</EM>)=3<EM>x</EM>+10: + +<P><PRE>(define (f x) ;; wrong! + (* x 3) + (+ x 10)) +</PRE> + +<P>Again, the first expression has no effect and Scheme will just +return the value <EM>x</EM>+10.<A NAME="text6" HREF="defining.html#ft6">[6]</A> + +<P>A very common pitfall in Scheme comes from choosing the name of +a procedure as a parameter. It doesn't come up very often with +procedures like the ones in this chapter whose domains and ranges +are both numbers, but it will be more likely later. If you have a +program like this: + +<P><PRE>(define (square x) + (* x x)) + +(define (area square) ;; wrong! + (square square)) +</PRE> + +<P>then you'll get in trouble when you invoke the procedure, for +example, by saying <CODE>(area 8)</CODE>. The <CODE>area</CODE> little person will +substitute <CODE>8</CODE> for <CODE>square</CODE> everywhere in the procedure definition, +leaving you with the expression <CODE>(8 8)</CODE> to evaluate. That expression +would mean to apply the procedure <CODE>8</CODE> to the argument <CODE>8</CODE>, but +<CODE>8</CODE> isn't a procedure, so an error message results. + +<P>It isn't a problem if the formal parameter is the name of a procedure that +you don't use inside the body. The problem arises when you try to use the +same name, e.g., <CODE>square</CODE>, with two meanings within a single procedure. +But special forms are an exception; you can never use the name of a special +form as a parameter. + +<P>A similar problem about name conflicts comes up if you try to +use a keyword (the name of a special form, such as <CODE>define</CODE>) as +some other kind of name—either a formal parameter or the name of a +procedure you're defining. We're listing this separately because the +result is likely to be different. Instead of getting the wrong value +substituted, as above, you'll probably see a special error message +along the lines of "improper use of keyword." + +<P>Formal parameters <EM>must</EM> be words. Some people try to write +procedures that have compound expressions as the formal parameters, like this: + +<P><PRE>(define (f (+ 3 x) y) ;; wrong! + (* x y)) +</PRE> + +<P>Remember that the job of the procedure definition is only to +provide a <EM>name</EM> for the argument. The <EM>actual</EM> argument isn't +pinned down until you invoke the procedure. People who write programs like +the one above are trying to make the procedure definition do some of the job +of the procedure invocation. + +<P><H2>Boring Exercises</H2> + +<P><B>4.1</B> Consider this procedure: + +<P><PRE>(define (ho-hum x y) + (+ x (* 2 y))) +</PRE> + +<P>Show the substitution that occurs when you evaluate + +<P><PRE>(ho-hum 8 12) +</PRE> + +<P> +<B>4.2</B> Given the following procedure: + +<P><PRE>(define (yawn x) + (+ 3 (* x 2))) +</PRE> + +<P>list all the little people that are involved in evaluating + +<P><PRE>(yawn (/ 8 2)) +</PRE> + +<P>(Give their names, their specialties, their arguments, +who hires them, and what they do with their answers.) + + +<P> +<B>4.3</B> Here are some procedure definitions. For each one, describe the function in +English, show a sample invocation, and show the result of that invocation. + +<P><PRE>(define (f x y) (- y x)) + +(define (identity x) x) + +(define (three x) 3) + +(define (seven) 7) + +(define (magic n) + (- (/ (+ (+ (* 3 n) + 13) + (- n 1)) + 4) + 3)) +</PRE> + + +<P> +<H2>Real Exercises</H2> + +<P><B>4.4</B> Each of the following procedure definitions has an error of some kind. +Say what's wrong and why, and fix it: + +<P><PRE>(define (sphere-volume r) + (* (/ 4 3) 3.141592654) + (* r r r)) + +(define (next x) + (x + 1)) + +(define (square) + (* x x)) + +(define (triangle-area triangle) + (* 0.5 base height)) + +(define (sum-of-squares (square x) (square y)) + (+ (square x) (square y))) +</PRE> + + +<P> +<B>4.5</B> Write a procedure to convert a temperature from Fahrenheit to Celsius, and +another to convert in the other direction. The two formulas +are <EM>F</EM>=<SUP><SMALL><SMALL>9</SMALL></SMALL></SUP>⁄<SUB><SMALL><SMALL>5</SMALL></SMALL></SUB><EM>C</EM>+32 and <EM>C</EM>=<SUP><SMALL>5</SMALL></SUP>⁄<SUB><SMALL>9</SMALL></SUB>(<EM>F</EM>-32). + + +<P> +<B>4.6</B> Define a procedure <CODE>fourth</CODE> that computes the fourth power of its +argument. Do this two ways, first using the multiplication function, +and then using <CODE>square</CODE> and not (directly) using multiplication. + + +<P> +<B>4.7</B> Write a procedure that computes the absolute value of its argument by +finding the square root of the square of the argument. + + +<P> +<B>4.8</B> "Scientific notation" is a way to represent very small or very large +numbers by combining a medium-sized number with a power of 10. For example, +5×10<SUP><SMALL>7</SMALL></SUP> represents the number 50000000, while 3.26×10<SUP><SMALL>-9</SMALL></SUP> +represents 0.00000000326 in scientific notation. Write a procedure +<CODE>scientific</CODE> that takes two arguments, a number and an exponent of 10, +and returns the corresponding value: + +<P><PRE>> (scientific 7 3) +7000 + +> (scientific 42 -5) +0.00042 +</PRE> + +<P>Some versions of Scheme represent fractions in <EM>a</EM>/<EM>b</EM> form, and +some use scientific notation, so you might see <CODE>21/50000</CODE> or <CODE>4.2E-4</CODE> +as the result of the last example instead of <CODE>0.00042</CODE>, but these are +the same value. + +<P>(A harder problem for hotshots: Can you write procedures that go in the +other direction? So you'd have + +<P><PRE>> (sci-coefficient 7000) +7 + +> (sci-exponent 7000) +3 +</PRE> + +<P>You might find the primitive procedures <CODE>log</CODE> and <CODE>floor</CODE> helpful.) + + +<P> +<B>4.9</B> Define a procedure <CODE>discount</CODE> that takes two arguments: an item's +initial price and a percentage discount. It should return the new price: + +<P><PRE>> (discount 10 5) +9.50 + +> (discount 29.90 50) +14.95 +</PRE> + +<P> +<B>4.10</B> Write a procedure to compute the tip you should leave at a restaurant. It +should take the total bill as its argument and return the amount of the +tip. It should tip by 15%, but it should know to round up so that the +total amount of money you leave (tip plus original bill) is a whole number +of dollars. (Use the <CODE>ceiling</CODE> procedure to round up.) + +<P><PRE>> (tip 19.98) +3.02 + +> (tip 29.23) +4.77 + +> (tip 7.54) +1.46 +</PRE> + +<P> + +<HR> +<A NAME="ft1" HREF="defining.html#text1">[1]</A> Technically, the entire +expression <CODE>(define (square x) &hellip)</CODE> is the special form; the word <CODE>define</CODE> itself is called a <EM>keyword</EM>. But in fact Lispians are +almost always loose about this distinction and say "<CODE>define</CODE> is a +special form," just as we've done here. The word "form" is an archaic +synonym for "expression," so "special form" just means "special +expression."<P> +<A NAME="ft2" HREF="defining.html#text2">[2]</A> Also, we'll sometimes use the terms "domain" and +"range" when we're talking about procedures, although technically, only +functions have domains and ranges.<P> +<A NAME="ft3" HREF="defining.html#text3">[3]</A> You know, that's +when you wave your hands around in the air instead of explaining what you +mean.<P> +<A NAME="ft4" HREF="defining.html#text4">[4]</A> You may be thinking that this is rather an +inefficient way to do things—all this copying and replacement before you +can actually compute anything. Perhaps you're afraid that your Scheme +programs will run very slowly as a result. Don't worry. It really +happens in a different way, but the effect is the same except for the +speed.<P> +<A NAME="ft5" HREF="defining.html#text5">[5]</A> Until we started defining our own procedures in this +chapter, all of the little people were hired by Alonzo, because all +expressions were typed directly to a Scheme prompt. Now expressions can +come from the bodies of procedures, and so the little people needed to +compute those expressions are hired by the little person who's computing +that procedure. Notice also that each little person <EM>reports to</EM> +another little person, not necessarily the one who <EM>hired</EM> her. In +this case, if Harry hires Shari for <CODE>sqrt</CODE>, Paul for <CODE>+</CODE>, and Slim +and Sydney for the two <CODE>square</CODE>s, then Slim reports to Paul, not to +Harry. Only Shari reports directly to Harry.<P> +<A NAME="ft6" HREF="defining.html#text6">[6]</A> This is especially problematic for people +who used to program in a language like Pascal or BASIC, where you say things +like "<CODE>X = X * 3</CODE>" all the time.<P> +<P><A HREF="../ss-toc2.html">(back to Table of Contents)</A><P> +<A HREF="../ssch3/people.html"><STRONG>BACK</STRONG></A> +chapter thread <A HREF="../ssch5/words.html"><STRONG>NEXT</STRONG></A> + +<P> +<ADDRESS> +<A HREF="../index.html">Brian Harvey</A>, +<CODE>bh@cs.berkeley.edu</CODE> +</ADDRESS> +</BODY> +</HTML> |