Our main objectives in this course are to learn about algorithms -- step-by-step methods for solving problems -- and to learn how to direct computers to perform such algorithms for us. A programming language, such as Scheme, is a formal notation in which one can express algorithms so exactly that a computer can perform them without any other assistance from human beings. The expression of an algorithm in such a notation is called a program, and the computer is said to be executing the program when it is performing the algorithm as directed.
Let's start with a very short Scheme program that directs the computer to find the answer to the question ``What is the square root of 137641?'' Here it is:
(sqrt 137641)
When this program is executed, the computer's central processor -- the electronic circuit that directs the movement and transformation of data inside the computer -- calculates the square root, and the DrScheme software takes the result of the calculation and displays it in the Interactions window:
371
When the central processor calculates a square root, it breaks the
computation down into a large number of much simpler steps. Some
programmers who are experts on square roots and on the idiosyncracies of
the Intel Pentium processor figured out and wrote down a step-by-step
method for computing the square root of any number, using only the very
elementary transformations that the processor can perform. DrScheme
recognizes sqrt as the name of this algorithm and knows where
the processor instructions that carry it out are stored. When DrScheme
receives a command to compute a square root, it recovers these instructions
and arranges for the processor to follow them.
Although it would be interesting and instructive to examine the method by
which the processor calculates square roots, at this stage it will be more
convenient for us to think of sqrt as a primitive
procedure, regarding the calculation of a square root as a single step
that is usually just part of a much larger program. The idea that a
computation can be regarded as a complicated sequence of instructions on
one level, and as a unit on another, more abstract level is very common in
computer science.
A program written in Scheme has a particularly simple structure: it is a
sequence of definitions and commands -- any number of them, in any order.
DrScheme reacts to each definition in a program by memorizing it, and to
each command by carrying out the command and displaying any results that it
produces. The expression (sqrt 137641) is a command --
``Compute the square root of 137641!'' -- and it produces one result, which
is duly displayed.
The full Scheme language that DrScheme supports contains several hundred primitive procedures -- operations, such as finding the square root of a number, for which DrScheme can use pre-packaged algorithms.
A procedure call is a command that directs DrScheme to activate a
procedure such as sqrt. (Note that `sqrt' is the
name of the procedure, and `(sqrt 137641)' is the procedure
call.) In Scheme, every procedure call begins with a left parenthesis and
ends with the matching right parenthesis. Within the parentheses, one
always begins by identifying the procedure to be called and then continues
by identifying the arguments -- the values that the procedure is
supposed to operate on. The sqrt procedure takes only one
argument -- the number of which you want the square root -- but other
procedures take two or more arguments, and some need no arguments at all.
All arithmetic in Scheme is done with procedure calls. The primitive
procedure + adds numbers together; the primitive procedure
- subtracts one number from another. Similarly, the primitive
procedure * performs multiplication, and the primitive
procedure / performs division. The fact that in a procedure
call the procedure is identified first makes calls to these procedures look
different from ordinary arithmetic expressions. For instance, to tell
DrScheme to subtract 68343 from 81722, one gives the command
(- 81722 68343)
If this command is the whole program, running it causes DrScheme to display the result:
13379
DrScheme learns new names for things by reading definitions. Here's what a definition looks like:
(define days-in-a-week 7)
Like a procedure call, a definition begins and ends with matching
parentheses. To distinguish between definitions and procedure calls,
DrScheme looks at what comes immediately after the left parenthesis. In a
definition, the keyword define must appear at that point.
Define is not the name of a procedure; it is a
keyword, constituting part of the syntax of the Scheme programming
language. Its only role is to serve as the mark of a definition.
After the keyword define, a definition contains the name being
defined and an expression that identifies the value that the name should
stand for. In this example, the name is days-in-a-week. (In
Scheme, a name can contain hyphens internally.) The value that it names is
the number 7. Once DrScheme has seen this definition, it remembers that
days-in-a-week stands for 7.
For example, here is a Scheme program that begins with the definition shown above, and continues with a command that uses the name that the definition introduces:
(define days-in-a-week 7) (* days-in-a-week 52)
When this program is executed, DrScheme displays the result of the computation that the command directs it to perform:
364
Since the value associated with the name days-in-the-week is
7, and the result of multiplying 7 by 52 is 364, this result is correct.
The value that gets a new name need not be a number; it can be anything,
even a procedure. For example, if you don't like the name *
for the multiplication procedure and would rather call it by the name
multiply, you can just start each program with the definition
(define multiply *)
At this point, I hope you're wondering what other useful and interesting procedures are built into Scheme. Section 6.2.5 of the Revised5 report on the algorithmic language Scheme contains a list of the ones that are mainly about numbers, and that's only one section of the full roster of standard Scheme procedures. Fortunately, most of the primitive procedures perform small, simple jobs and are easily learned.
When you start DrScheme, the window that first appears is divided horizontally into two subwindows: a Definitions window (on top), in which you'll develop and modify your programs, and an Interactions window (on the bottom), in which you'll experiment with them and test them.
Although you can type anything you want to into the Definitions window, DrScheme expects to find a Scheme program there, and makes some assumptions about how to format what you type that are based on this assumption. DrScheme executes the program in the Definitions window only when you click on the Execute button.
In the Definitions window, you can perform a variety of editing operations to modify the text of the program:
Typing a letter, a digit, or a punctuation mark adds it to the text at the position indicated by the thin, blinking, black bar (the editing cursor).
Pressing the <Backspace> key deletes the character to the left of the editing cursor, or the preceding line break if the editing cursor is at the beginning of a line.
The arrow keys move the editing cursor around within the region occupied by text.
Positioning the pointer within the text region and clicking the left mouse button causes the editing cursor to jump to that point.
To delete a big chunk of text, move the pointer to the beginning of the
chunk, then press and hold the left mouse button while moving the pointer
to the other end of the chunk. The selected chunk will be ``blacked out''
(displayed in white letters against a black background). Then bring up
the
Edit menu and select the Cut operation. This
removes the blacked-out text.
If you have deleted a chunk of text with Cut, you can put it
back in somewhere else, if you want to, by positioning the editing cursor
at the insertion point and selecting Paste from the
Edit menu.
If you make a mistake and create a big mess in your window, select
Undo from the Edit menu to put the window back
to
the way it was before and try again. You can select Undo
repeatedly to reverse the effects of a sequence of editing steps.
(If you're curious about the rest of the operations listed on the
Edit menu, you can find explanations of them in ``Using
DrScheme: Interface reference: Menus: Edit,'' a section of the PLT
DrScheme Programming Environment Manual. Still more editing
operations
are discussed in the section ``Using
DrScheme: Interface reference: Keyboard shortcuts.'')
Programs are intended to be read both by people and by computers. Because people understand much richer and more flexible notations than computers -- real languages, as opposed to the extremely limited pseudo-languages used to direct the execution of algorithms -- it is essential to be able to include comments in program files. Comments are intended exclusively for human readers; the computer ignores them as if they were so much blank space.
In a Scheme program, any line that begins with one or more semicolons is a comment:
; This is a comment. DrScheme will store it along with the ; rest of the text of a program, but does not even attempt to ; execute any part of it. ;;; The following definition, however, is read and processed: (define centimeters-in-an-inch 254/100) ;;; And the following expression is evaluated when this program is ;;; executed: (* 36 centimeters-in-an-inch)
It is also possible to place a comment to the right of a definition or command. The semicolon and everything to its right (on the same line) are ignored during execution.
(define centimeters-in-a-foot (* 12 centimeters-in-an-inch)) ; One foot equals twelve inches.
We'll use comments for several purposes in Scheme programs:
Definitions are seldom completely self-explanatory. Usually, you'll want to preface each definition with a comment explaining what you want to define and how you want to define it.
;;; The number of seconds in a day is the product of the ;;; number of hours in a day (twenty-four), the number of ;;; minutes in each hour (sixty), and the number of seconds ;;; in each minute (also 60). (define seconds-in-a-day (* 24 60 60))
I recommend that you write the comment before writing the actual definition. Writing the comment helps the programmer articulate and specify the idea that the definition will express. Especially when you're just starting to program, it's useful to separate this stage of clarifying your ideas from the stage in which you have to think about the syntactic structure of the programming-language notation and the idiosyncrasies of Scheme's expression-evaluator.
If the calculation that your program performs is tricky or subtle, or if it depends on some non-obvious condition that is satisfied in one particular case but usually can't be relied on, you should insert a comment to explain what's going on:
(quotient total sample-size) ; The sample size cannot be zero,
; since at least one sample is
; constructed by the BASE-SAMPLE
; procedure.
Even if you are the only one who will ever read your program, your future self, trying to understand the program, may need a reminder or two. It is astonishing, incidentally, how quickly this sort of detail fades from one's memory. Write it down, even if you don't now expect to forget it.
Since it's so easy to exchange programs over the Internet, programs that you write and send to others will eventually reach people who have never heard of you. It's a good idea to include a comment at the beginning of each program identifying yourself as the author and explaining how to reach you in case the reader has questions about your program:
;;; John David Stone ;;; Department of Mathematics and Computer Science ;;; Grinnell College ;;; stone@cs.grinnell.edu ;;; created October 14, 1997 ;;; last revised August 27, 2001
A long program usually begins with a long opening comment that explains the purpose and structure of the program and presents an overview of what is to come. Here's a real-world example:
;;; The Apache server for hypertext documents records ;;; information about its actions in two log files, ;;; access_log and error_log. This program parses those ;;; logs and generates a summary of their contents for the ;;; benefit of the webmaster.
Using comments, you can and should think of writing a program as rather like writing an essay in which you describe the problem you're trying to solve and your method of solution. The code sections fit into such an essay as exhibits showing the exact, formal algorithms that express your solution.
In the Interactions window, insertion and deletion operations work only in the region following the last prompt. The idea is that you cannot change the past: You can't go back and un-give commands that you have already given, and that DrScheme has already responded to. The Interactions window is supposed to contain an accurate transcript of what has been done and cannot be undone.
However, while you're working on a command -- even a complicated one that extends over several lines -- the editing operations work exactly as they do in the Definitions window. There is also one extra editing operation: If you press the <Esc> key (in the upper left-hand corner of our keyboards) and then the <P> key (for ``previous''), DrScheme makes a copy of the last command or definition that it processed in the Interactions window and places it after the prompt, so that you can revise it or repeat it easily.
Most of the writing that you do while developing a Scheme program takes place in the Definitions window. That's the place in which you record definitions that you want to keep, commentary about your program, sample calls to procedures, test cases, and so on.
If there are definitions and commands that you want to keep track of (so that you don't have to retype them from scratch later on, for instance), but that you don't want DrScheme to execute as part of your program, you can ``comment them out'' by putting a semicolon at the beginning of every line that they occupy. You can even comment out a large block of code in one step by first selecting the block (holding down the left mouse button while dragging the mouse over it) and then clicking on the word Scheme on the menu bar and clicking on Comment Out on the menu that appears.
The item Uncomment on that same menu has the opposite effect: It removes a semicolon from the beginning of each line in the selected block.
Once you have saved a program in a file, as described in the ``Beginning Scheme'' handout, you can load it into DrScheme again from that file, in order to execute it, to modify or extend it, or just to read it over again. In fact, there are several different ways to recover the contents of DrScheme files.
The most straightforward method is to select the Open command
from
the File menu, and edit the white text field on the window
that appears (the one labelled ``Full pathname'') so that it contains the
name of the file in which your program is stored:
Clicking on the OK button in the lower right-hand corner
loads
your program. Depending on whether the Definitions or Interaction window
is free at the time you load the program, DrScheme either places the
program in the appropriate window or creates a new frame-and-window
combination and loads the program into it. In the latter case, DrScheme
usually displays the program in only one text area. You can make the
other
one visible by selecting Show Interactions or Show
Definitions (as appropriate) from the Show menu.
If you just want to execute the program in the file, rather than having it
displayed on the screen, you can use a standard Scheme procedure called
load. When invoked, load directs DrScheme to
open a file and quickly read the program that it contains, memorizing each
definition and executing each command. The load procedure
takes one argument, a character string giving the name of the
file
in which the program is stored.
The term characters refers generically to letters, digits,
punctuation marks, and such like -- the lowest-level constituents of text.
A character string is a sequence containing any number of
characters, ``strung together'' in a linear order. In Scheme, a character
string is usually written just by placing the character sequence between
double quotation marks. For instance, the string consisting of the three
lower-case letters c, a, and t, in that order, is
written in Scheme as "cat". (Without the quotation marks,
Scheme would incorrectly interpret cat as a symbol like
sqrt or area, and expect it to stand for
something further.)
Here, then, is what a call to the load procedure looks like.
This one expresses the command ``Execute the contents of the file named
frogs.ss!''
(load "frogs.ss")
The parentheses enclose the procedure call and contain the name of the
procedure, load, and the operand, "frogs.ss".
DrScheme provides a lot of documentation about Scheme on-line. The usual entry point is the help desk, a browser that knows where to find all the documentation and provides access to it.
To activate the help desk, select Help Desk from the
Help menu. Clicking on the first link in the Help Desk
window brings up a short introductory document, ``How to use Help Desk.''
This document is available on the World Wide Web as
http://www.cs.grinnell.edu/~walker/courses/151.sp04/readings/beginning-Scheme.xhtml
|
created August 23, 1997 and
revised August 6, 2002 by
John David Stone
(stone@cs.grinnell.edu)
and
Ben Gum
(gum@cs.grinnell.edu) last revised January 18, 2004 by Henry M. Walker at walker@cs.grinnell.edu. |
|
| For more information, please contact Henry M. Walker at walker@cs.grinnell.edu. |