ECS 15 -- Fall 1997 -- © Nancy E. Reed, 1997

Laboratory 7 Notes
Flow Control Statements (Sequence, Selection, Iteration)
Lists, and Recursive Functions.

Handouts:

Readings:

Useful editor functions

The Edwin editor has functions for marking, cutting, copying, and pasting areas of text. Some of these functions you might find particularly useful for the lab this week.

Use auto-indentation to see the structure of your functions (instead of counting parentheses):

List manipulation functions

Scheme has a built-in data type called lists. Lists are a simple and flexible way to store data (and Scheme uses them to store functions, too)! Powerful list manipulation functions are available to work with this type of data (also called a data structure). You will be using the following functions in this lab and the remaining labs.

Program Flow Control Structures

Computer program statements can be executed in order, or execution can "jump" to a different function/procedure or a different part of the current procedure with program flow control statements.

Program flow control within a function or procedure is accomplished with flow control statements. There are three categories of flow control statements, sequence (top to bottom), selection (choosing one of many different alternatives), and iteration (loops). Reference the Programming in Scheme 2 handout for a large list of program flow control statements with examples in Scheme.

Predicate functions

Functions that perform tests - by comparing values, for example, are necessary to provide execution flow control in programs. Predicates, or boolean (True/False) testing functions, are used in the tests of conditional statements, in iteration statements, and in recursion. Some representative Scheme predicate functions are shown next.

Sequential statements - Execution Flow control

The default in Scheme is that statements are executed in order, from top to bottom. There are also built-in functions that allow the programmer to specify sequential evaluation, but also may allow some statements to be skipped.

A statement that specifies explicitly to perform statements in order is the begin statement.

(begin
  statement1
  statement2
  .....
  statementN   )
Example:
(begin
  (display x)
  (display y)
  (newline))

The other two sequential control structure functions you have just seen above - and and or. They return a (boolean or true/false) value and are also sequential control structures. They are control structures because of the short-circuit evaluation of their arguments. Please see the examples in the Scheme 2 handout.

Selection statements - Execution Flow control

One very flexible selection statement in Scheme is the cond statement. The syntax for cond follows:
(cond
  ( < test1 >   < actions > *)
  ( < test2 >   < actions > *)
  .....
  ( < testN >   < actions > *)
  )

The cond statement contains a series of tests and actions. The tests usually make use of predicate functions as described above. When evaluating the cond statement, each of the tests is evaluated, in order from top to bottom, until one returns true or the end of the cond statement is reached. If a test returns true, then all the actions in that clause are performed, and the cond statement exits with the result produced by the last statement in the clause (no tests or actions below that "successful" test are executed). If all tests return false, then none of the actions are performed and false is returned.

Because the statement exits after performing the actions for the first true test, none of the tests or actions will be performed in clauses that follow the first clause with a test evaluating to true. The last test is often the symbol else, that always evaluates to true. Would it make any sense to put this anywhere but as the last test?

Example: Electronic-Bouncer

(define  (electronic-bouncer  age)
  (cond
   ((< age 21)
    (newline)
    (display "You are not old enough.  You may not enter the bar."))
   (else
    (newline)
    (display  "You are old enough.  You may enter the bar.  Enjoy!"))  )  )

The function electronic-bouncer takes one argument which should be a number representing a person's age in years. This function checks the number given as an argument, and if it is less than 21, it prints the message
You are not old enough. You may not enter.
Otherwise, the number must be 21 or greater and it prints the message
You are old enough. You may enter. Enjoy!

Example: Check-soup

(define  (check-soup  temp)
  (cond
   ((>= temp 200)
    (newline)
    (display "it is too hot!"))
   ((<= temp 110)
    (newline)
    (display "It is too cold!"))
   (else
    (newline)
    (display "it is just right!"))   )  )

The function check-soup takes one argument which should be a number representing the temperature of a bowl of soup. This function checks the number given as an argument, and if it is greater than or equal to 200, it prints the message
It is too hot!
Otherwise, if the number is less than or equal to 110, it prints the message
It is too cold!
Otherwise, the number must be less than 200 and greater than 110 and it prints the message
It is just right!

Iteration (Loops) - Execution Flow Control

Iteration means to repeat some section of code (called the body of the loop) a number of times depending on a test or some specific number of times. Loops are a very space-saving way to accomplish tasks that do the same or similar things repeated times.

An example of a program with a loop is the function countdown shown below from the file loops.scm.

In Scheme, a powerful iteration command is called do. The syntax of do is as follows:

(do 
  ( (variable1 initial-value1 step1) ; create/initialize local variables
    (variable2 initial-value2 step2) ;  the "step" will modify the variable 
		   	             ;  each time the loop executes
    (variable2 initial-valuen stepn))
  ( termination-test		     ; Exit test performed each time 
                                     ;    through the loop.
    terminal-action1		     ; If the test returns true, the 
                                     ;    following actions are performed.  
    terminal-actionm)                ; Then the loop terminates - control
                                     ;   starts at the statement following
                                     ;   the end of the do statement
                                     ; BODY of the loop
   action1			     ; If the test returns false, the 
                                     ;   actions in the body are performed 
      				     ;   and we return to the top of the loop,
   actionx  )			     ;   perform the "step" on the variables,
				     ;   and continue to the exit test.

Each loop can have local variables that are initialized and can be automatically updated each time the loop is performed. Each loop also has an exit condition, to test if the loop has finished, and possibly exit actions, actions to be performed just before exiting the loop. If the exit condition is not true, then the exit actions are skipped and we continue to the body of the loop. In the body of the loop are the actions (statements) that are performed each time through the loop. Once all the actions in the body of the loop are performed, control returns to the top of the loop where automatic updating of the loop variables is performed then the exit condition is performed, etc.

;  function COUNTDOWN
;    Takes one argument - a NUMBER
;    I/O: Prints a count starting from NUMBER down to 1
;      Then prints "Blastoff!!!"
;    No side effects.
;    Does not return anything important.
;    This version is iterative - using a DO loop.

(define (countdown number)        
  (do                            ; Start the loop
    ((count number (- count 1))) ; Loop variable - COUNT - start at NUMBER
                                 ;   COUNT decreases by 1 each time 
    ((equal? count 0)            ; termination test - if COUNT is zero
     (newline)                   ;  at loop termination - start a new line
     (display "Blastoff!!!"))    ;  at loop termination - write message
    (newline)                    ; body of the loop - start on a new line
    (display count)              ; body of the loop - write the COUNT
    )                            ; return to the top of the DO loop
  )                              ; end of the function definition.

Iteration Example: The procedure Average

Reference the code for the function average in your handout, and it the file loops.scm

This function was executed with the following data: The input numbers are: 6, 4, 11, and 999. The result should be 7.

Here is the transcript of the procedure average working on this example data:

[??] (average)
This program will find the average of numbers you enter
through the keyboard.  Type 999 to indicate the end of data.

Please enter a number:   6
Please enter the next number:   4
Please enter the next number:   11
Please enter the next number:   999
The average of the numbers is:   7

;Unspecified return value

Exactly what happened during this example?

The result (7) is printed to the screen (by the print part of the read, eval, print loop).

See the other examples of iteration in the loops.scm file.

Recursion

Above you have seen special statements to control the order of execution of statements within one function or procedure. The other primary method of controlling program execution shifts control out of the current function and into another function by the use of a procedure/function invocation or procedure/function call.

Recursion is a special case of function invocation when a function calls (a copy of) itself to solve part of the problem. In order to avoid "infinite loops" - where there is no termination to the function calls, the programmer must be careful to make sure that each recursive call is on a smaller problem. We will discuss recursion in more detail in the following lectures and in lab. Please also see the examples in the recurse.scm file.

Example: write-sentence

(define (write-sentence number)
  (cond
    ((equal? number 0)
     (newline)
     (display "Done."))
    (else
     (newline)
     (display "Writing one sentence.")
     (write-sentence (- number 1)))))

The function write-sentence takes one argument which should be a number. It will write the string "Writing one sentence." the exact number of times specified in the argument number. At the end, it will print the string "Done.".

For example
(write-sentence 6)

will produce
Writing one sentence.
Writing one sentence.
Writing one sentence.
Writing one sentence.
Writing one sentence.
Writing one sentence.
Done.

Go to the index of lectures for ECS15 - Fall 1997 .

Go to the homepage for ECS15 - Fall 1997 .

© Nancy E. Reed, 1997 -- nereed@ucdavis.edu