Our objective in this course is 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.
Although not all of the problems that we'd like computers to solve are arithmetical, the simplest examples belong to that category, and we'll start with a few of them. Here, for instance, is a program, written in Scheme, that directs the computer to find the answer to the question ``What is the square root of 137641?''
(sqrt 137641)
Let's begin today's lab by finding out how to get Scheme to execute this program and thereby answer the question.
Log in on any MathLAN workstation. If no dtterm window appears automatically, start one by clicking on the monitor-and-keyboard icon on the front panel. Type scheme at the shell prompt to start the Chez Scheme interactive interface, a program designed precisely to read in and execute programs written in Scheme.
When the Scheme prompt (a greater-than sign) appears, type in the program shown above. Press the <Enter> key after the right parenthesis. As soon as the interactive interface receives your program, it will execute it and print out the result of its computation. Because this particular program is extremely simple, the result will be printed immediately. At that point, the window should look like this:
bourbaki% scheme Chez Scheme Version 5.0c Copyright (c) 1994 Cadence Research Systems > (sqrt 137641) 371 >
It is not difficult to check, by pencil-and-paper computation or with the help of a pocket calculator, that 137641 is indeed the square of 371. (You don't have to take my word for it -- check it yourself.) So this first program is a success.
You probably noticed that Chez Scheme prints out another prompt after
executing your program. This is because Chez Scheme cannot be sure that
it has seen all the steps in the program. 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. The Scheme interactive
interface reacts to each definition by memorizing it and to each command by
carrying out the command. (The expression (sqrt 137641) is a
command -- ``Compute the square root of 137641!'') Because a program might
contain several commands rather than just one, the interactive interpreter
has to be prepared to receive another after carrying out the first.
The <Ctrl/D> that you type to exit from the interactive interface is really a signal indicating the end of a program that consists of all the definitions and commands that you have issued during your session with Chez Scheme. Chez Scheme will always expect another input and generate another prompt until it receives some such signal and exits.
The Chez Scheme interactive interface contains several hundred
built-in procedures -- operations, such as finding the square root
of a number, for which the interface can use prepackaged algorithms. Some
programmer who is an expert on square roots and on the idiosyncracies of
the HP workstations' central processing unit (the electronic
circuit that directs the movement of data inside the computer) has figured
out and written up a step-by-step method for computing the square root of
any number, using only the very elementary transformations that the central
processing unit can perform. Chez Scheme recognizes sqrt as
the name of this algorithm and knows where the processor instructions that
carry it out are stored. When Chez Scheme receives a command to compute a
square root, it recovers these instructions and executes them.
A procedure call is a command that directs the interactive
interface to activate a built-in procedure such as sqrt.
(So sqrt is 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 operands -- the values that
the procedure is supposed to operate on. A call to the sqrt
procedure has only one operand -- the number of which you want the square
root -- but other procedures can have two or more operands, and some have
no operands at all.
All arithmetic in Scheme is done with procedure calls. The built-in
procedure + adds numbers together, the built-in procedure
- subtracts one number from another. Similarly, the built-in
procedure * performs multiplication, and the built-in
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 Chez
Scheme to subtract 68343 from 81722, one gives the command (- 81722
68343), thus:
> (- 81722 68343) 13379
Tell Chez Scheme to multiply 383 by 1162.
The Scheme procedure abs computes the absolute value of its
operand. Tell Scheme to compute the absolute value of -153.
The Scheme procedure for raising a number to some power is called
expt. Tell Scheme to find the cube of 171 (that is, to raise
171 to the power 3).
It is harmless, though unproductive, to try to give Chez Scheme ordinary arithmetic expressions, in which the procedure is written between the operands. Try it: Type each of the following expressions at the Scheme prompt and see what reaction you get.
Here are the explanations:
When Chez Scheme sees the left parenthesis at the beginning of the
expression (2 + 3), it expects the expression to be a
procedure call, and it expects the procedure to be identified right after
the left parentheses. But 2 does not identify a procedure; it
stands for a number. So Chez Scheme complains that it cannot ``apply'' or
execute something that is not a procedure.
In the absence of parentheses, Chez Scheme sees 7 * 9 as three
separate and unrelated expressions -- the numeral 7;
*, a name for the built-in multiplication procedure; and
9, another numeral. It interprets each of these as a command
to evaluate an expression: ``Compute the value of the numeral
7! Find out what the name * stands for! Compute
the value of the numeral 9!'' So it performs the first of
these commands, displays 7, and issues a prompt; then it
carries out the second command, reports that * is the name of
the system procedure *, and issues another prompt; and finally
it carries out the third command, displays the result, 9, and
issues yet another prompt. This behavior is confusing, but it's strictly
logical if you look at it from the computer's point of view (remembering
that the computer has absolutely no common sense).
As in the preceding case, Chez Scheme sees this as two separate commands:
sqrt means ``Find out what sqrt is!'' and
(49) means ``Call the procedure 49, with no
operands!'' Chez Scheme responds to the first command by reporting that
sqrt is the system procedure sqrt and to the
second by pointing out that the number 49 is not a procedure.
The interactive interface can also learn 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, Chez
Scheme looks at what comes right 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 part of
the syntactic structure 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 --
notice that in Scheme the symbol that names something can (and often does)
contain hyphens internally -- and the value that it names is the number 7.
Once Chez Scheme has seen this definition, it remembers that
days-in-a-week stands for 7:
> (define days-in-a-week 7) > (* days-in-a-week 5) 35
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, just start each session with Chez Scheme by typing
in (define multiply *).
Write a definition that will cause Scheme to recognize dozen
as a name for the number 12.
Write a definition that will cause Scheme to recognize
raise-to-power as a synonym for expt.
At this point, I hope you're wondering what other useful and interesting procedures are built into Scheme. Section 6.5.5 of the Revised4 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 built-in procedures perform small, simple jobs and are very easily learned.
This document is available on the World Wide Web as
http://www.math.grin.edu/~stone/courses/scheme/beginning-Scheme.html
created August 23, 1997
last revised August 29, 1997