As section 2.2 of the textbook explains, a programmer can have Scheme
construct a new procedure, not equivalent to any of the built-in ones, by
writing a lambda-expression. For instance, Scheme recognizes
the expression
(lambda (root) (* root root))
as a description of a procedure that, when called, squares its argument. Like any other value, this procedure can be given a name by means of a definition:
;;; square: multiply a given number by itself
;;; John David Stone
;;; Department of Mathematics and Computer Science
;;; Grinnell College
;;; stone@cs.grinnell.edu
;;; created February 13, 1999
last revised March 17, 2000
;;; Given:
;;; ROOT, an exact number.
;;; Result:
;;; SQUARED, an exact number.
;;; Preconditions:
;;; None.
;;; Postcondition:
;;; SQUARED is the product of ROOT and ROOT.
(define square
(lambda (root)
(* root root)))
Such a procedure can be called, just as if it were a built-in procedure:
> (square 12) 144
One foot is equal to 761/2500 meters (exactly). Define a procedure named
feet->meters that takes one argument, a real number
representing a length measured in feet, and returns the number that
represents the same length as measured in meters. Use this procedure to
determine the number of meters in one mile (5280 feet).
The price of admission to see a first-run movie at the Bijou Theatre is
seven dollars for an adult, four for a child. Define a procedure named
gross-receipts that takes two arguments, the number of adults
and the number of children admitted, and returns the total amount that they
paid for admission, in dollars. For instance, if the audience included
exactly 112 adults and six children, the procedure should return the sum of
112 times seven and four times six, which is 808:
> (gross-receipts 112 6) 808
Use your procedure to determine the total admission for eighty-two adults and 146 children.
In a figure-skating competition, judges have observed the competitors' performances and awarded three separate scores to each competitor: one for accuracy, one for style, and one for the difficulty of the chosen routine. Each score is in the range from 0 to 10. The rules of the competition specify that a competitor's three scores are to be combined into a weighted average, in which accuracy counts three times as much as difficulty and style counts twice as much as difficulty. The overall result should be a single number in the range from 0 to 10.
Write a comment in which you describe the nature and purpose of a procedure that takes three arguments -- a competitor's accuracy, style, and difficulty scores -- and returns their weighted average. Then define the procedure that you have described. Next, test your procedure, looking for cases in which the weighted average is computed incorrectly. (If you find any, make corrections in your definition.) Finally, save the procedure and documentation in an appropriately named file.
A Boolean value is a datum that reflects the outcome of a single
yes-or-no test. For instance, if one were to ask Scheme to compute whether
the empty list has five elements, it would be able to determine that it
does not, and it would signal this result by displaying the Boolean value
for ``no'' or ``false,'' which is #f. There is only one other
Boolean value, the one meaning ``yes'' or ``true,'' which is
#t. (These are called ``Boolean values'' in honor of the
logician George
Boole, who was the first to develop a satisfactory formal theory of
them.)
A predicate is a procedure that always returns a Boolean value. A
procedure call in which the procedure is a predicate performs some
yes-or-no test on its arguments. For instance, the predicate
number? -- the question mark is part of the name of the
procedure -- takes one argument and returns #t if that
argument is a number, #f if it does not. Similarly, the
predicate even? takes one argument, which must be an integer,
and returns #t if the integer is even and #f if
it is odd. The names of most Scheme predicates end with question marks,
and I recommend this useful convention even though it is not required by
the rules of the programming language.
Here is a selection of ``primitive'' (that is, built-in) Scheme predicates:
number? tests whether its argument is a number.symbol? tests whether its argument is a symbol.string? tests whether its argument is a string.procedure? tests whether its argument is a
procedure.list? tests whether its argument is a list.null? tests whether its argument is the empty list.boolean? tests whether its argument is a Boolean
value.eq? tests whether its two arguments are identical, in
the very narrow sense of occupying the same storage location in the
computer's memory. In practice, this is useful information only if at
least one argument is known to be a symbol or a Boolean value.eqv? tests whether its two arguments ``should normally be
regarded as the same object'' (as the language standard declares). Note,
however, that two lists can have the same elements without being ``regarded
as the same object.'' Also note that in Scheme's view the number 5, which
is ``exact,'' is not necessarily the same object as the number 5.0, which
might be an approximation.equal? tests whether its two arguments are the same or,
in the case of lists, whether they have the same contents.= tests whether its arguments, which must all be
numbers, are numerically equal; 5 and 5.0 are numerically equal for this
purpose.< tests whether its arguments, which must all be
numbers, are in strictly ascending numerical order.> tests whether its arguments, which must all be
numbers, are in strictly descending numerical order.<= tests whether its arguments, which must all be
numbers, are in ascending numerical order, allowing equality.>= tests whether its arguments, which must all be
numbers, are in descending numerical order, allowing equality.even? tests whether its argument, which must be an
integer, is even.odd? tests whether its argument, which must be an
integer, is odd.zero? tests whether its argument, which must be a
number, is equal to zero.positive? tests whether its argument, which must be a
real number, is positive.negative? tests whether its argument, which must be a
real number, is negative.
Call each of the predicates on the preceding list twice -- once with an
argument that ensures that the value of the procedure call is
#t, once with an argument that makes the value #f.
Another useful Boolean procedure is not, which takes one
argument and returns #t if the argument is #f and
#f if the argument is anything else. For example, one can
test whether the square root of 100 is unequal to the absolute value of
-12 by giving the command
(not (= (sqrt 100) (abs -12)))
If Scheme says that the value of this expression is #t, then
the two numbers are indeed unequal.
A few lines up, I said that not is a procedure in Scheme.
What procedure could you call to find out whether this assertion is true?
The symbol not is the name of the procedure discussed
in the preceding exercise, but the symbol itself, considered as a datum, is
not a procedure. Does Scheme agree with this classification? How
could one ask Scheme whether the symbol not is a
procedure?
Define a predicate bigger? that takes two real numbers as
arguments and returns #t if the absolute value of the first is
greater than the absolute value of the second, #f if it is
not. Call your procedure twice -- once with arguments that ensure that
the value of the procedure call is #t, once with arguments
that make the value #f.
This document is available on the World Wide Web as
http://www.cs.grinnell.edu/~stone/courses/scheme/procedure-definitions.xhtml
created September 2, 1997
last revised March 17, 2000