Beginning Scheme

Algorithms and programs

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.

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.

Interacting with DrScheme

Log in on any MathLAN workstation. If no terminal emulator appears automatically, start one by clicking on the monitor-and-keyboard icon on the front panel. Type drscheme & at the shell prompt to start the DrScheme programming environment.

In the interactions window -- the lower of the two large text areas -- DrScheme displays a one-line greeting, a reminder of which dialect of Scheme it expects to see, and a prompt (in this case, a greater-than sign), indicating that DrScheme is ready to deal with any command that you type in.

Welcome to DrScheme, version 101.
Language: Graphical Full Scheme (MrEd.)
>

Move the mouse pointer to the right of the prompt, click the left mouse button, and type in the program shown above. (If you prefer, you can select it from the Netscape Navigator window by moving the mouse pointer to the beginning of the program, pressing and holding the left mouse button, dragging the mouse pointer to the end of the program, and releasing the left mouse button. The background color against which the text that you have selected changes to yellow during this process, so that you can see the boundaries of the selection clearly. You can then paste the selected text into the interactions window by moving the mouse pointer to the right of the prompt and clicking the middle mouse button.)

Press the <Enter> key after the right parenthesis. At this point, DrScheme examines your program, translates it into a sequence of instructions to the computer's central processor (the electronic circuit that directs the movement and transformation of data inside the computer), executes it, and prints out the result of its computation. Because this particular program is extremely simple, the result is printed immediately. When the processing is complete, the interactions window looks like this:

> (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 DrScheme prints out another prompt after executing your program. This is because DrScheme 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. DrScheme reacts to each definition that you type into the interactions window 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, DrScheme has to be prepared to receive another after carrying out the first.

Procedure calls

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 prepackaged algorithms. Some programmers who are experts on square roots and on the idiosyncracies of the HP workstations' processor have 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 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.

A procedure call is a command that directs DrScheme to activate a procedure such as sqrt. (Note: 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), thus:

> (- 81722 68343)
13379
>


Exercise 1

Tell DrScheme to multiply 162 by 1383.


Exercise 2

The Scheme procedure abs computes the absolute value of its argument. Have DrScheme compute the absolute value of -197.


Exercise 3

The Scheme procedure for raising a number to some power is expt. Call this procedure to compute the cube of 19 (that is, the result of raising 19 to the power 3), and again to compute the nineteenth power of 3. What does this indicate about the relationship between procedures and argments in Scheme?


Exercise 4

It is harmless, though unproductive, to try to give DrScheme 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.

  1. (2 + 3)
  2. 7 * 9
  3. sqrt(49)

Here are the explanations:

  1. When DrScheme 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 parenthesis. But 2 does not identify a procedure; it stands for a number. (A ``procedure application'' is the same thing as a procedure call.)

  2. In the absence of parentheses, DrScheme sees 7 * 9 as three separate and unrelated expressions -- the numeral 7; *, a name for the primitive 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 and displays 7; then it carries out the second command, reporting that * is the name of the primitive procedure *; and finally it carries out the third command and displays the result, 9. This behavior is confusing, but it's strictly logical if you look at it from the computer's point of view (remembering, of course, that the computer has absolutely no common sense).

  3. As in the preceding case, DrScheme sees sqrt(49) as two separate commands: sqrt means ``Find out what sqrt is!'' and (49) means ``Call the procedure 49, with no arguments!'' DrScheme responds to the first command by reporting that sqrt is the primitive procedure for computing square roots and to the second by pointing out that the number 49 is not a procedure.


Definitions

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, 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 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 a name can, and often does, 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:

> (define days-in-a-week 7)
> (* days-in-a-week 52)
364
>

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 DrScheme by giving it the definition (define multiply *).


Exercise 5

Write a definition that will cause Scheme to recognize dozen as a name for the number 12.


Exercise 6

Write a definition that will cause Scheme to recognize raise-to-power as a synonym for expt.


The definitions window

The upper text area in the DrScheme window, which is called the definitions window, is used when you want to prepare a program ``off-line,'' that is, without immediately executing each step. Instead of processing what you type line by line, DrScheme waits for you to click on the button labelled Execute (the second button from the right, in the row just below the menu bar) before starting to execute the program in the definitions window. If you never click on that button, fine -- your program is never executed.

As its name implies, the definitions window usually contains definitions rather than commands, although either kind of expression can be written in either window. The difference is simply that we generally want an immediate response to a command, whereas definitions are usually processed in bulk.

Warning: When you click on the Execute button, the contents of the interactions window are erased. The idea is that executing the program in the definitions window may invalidate the results of previous interactions. Erasing the results that may now be inconsistent with the new definitions ensures that all visible interactions use the same vocabulary. This is actually a helpful feature of DrScheme, but it can take you by surprise the first time you see it happen. Just make sure that you have everything you need from the interactions window before clicking on Execute.


Exercise 7

Copy the definitions you wrote for exercises 5 and 6 into the definitions window and execute them.


You can save the contents of either window in a file at any time by selecting Save Definitions As Text or Save Interactions As Text from the File menu. DrScheme pops up a window in which you can specify the name of the file:

(screenshot)

Edit the contents of the white text field near the bottom of the pop-up window, adding a slash and the name of the file. Click on the OK button to dismiss the pop-up window.


Exercise 8

Save the definitions that you copied into the definitions window in exercise 7 in a file named beginning-Scheme.ss. (Conventionally, the names of files containing Scheme programs end in .ss or .scm.)


More procedures

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.


This document is available on the World Wide Web as

http://www.cs.grinnell.edu/~stone/courses/scheme/beginning-Scheme.html

created August 23, 1997
last revised March 17, 2000

John David Stone (stone@cs.grinnell.edu)