Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
1 Getting Started
> (+ 2 3)
5
> (+ (* 4 5) 3)
23
1
2. Getting Started in DrScheme 2
> x
7
Lists are a basic data type. There is the empty list, denoted null. To test
whether a list x is empty, use (null?x), which returns #t if x is null, and #f
otherwise.
If the list x = (a1 a2 . . .) is nonempty, then the element a1 is (car x) and the
list of all but the first element is (cdr x).
Functions are values, too.
(define square
(lambda (x) (* x x)))
Perhaps more conveniently, but with some loss of clarity, we can omit ’lambda’
(define (square x)
(* x x))
Some names are local (such as y below), while others are global (x below):
(define (add-x y)
(+ x y))
(define (cube x)
(* x (square x)))
(define (myabs x)
(cond ((> x 0) x)
((= x 0) 0)
(else (* -1 x))))
or
(define (myabs x)
2
2. Getting Started in DrScheme 3
(if (>= x 0) x
(* -1 x)
); end if
); end define
(if (P) A
B)
is equivalent to
(cond
((P) A)
(else B)
)
Note: cond can be used when there are more than just two alternatives.
Let’s write a program to compute the maximum of two inputs
(define (mymax x y)
(cond ((> x y) x)
(else y)))
(define (sum-squares x y z)
(let ((m (min x y z)))
(cond ((= m x) (+ (square y) (square z)))
((= m y) (+ (square x) (square z)))
(else (+ (square x) (square y))))))
(define (square x)
(* x x))
3
2. Getting Started in DrScheme 4
Here, min is a pre-defined function, of arbitrary arity let is a special form – the
effect above is to define m locally.
What about repeating functions? First, recursion:
(define (fact x)
(cond ((= x 0) 1)
(else (* x (fact (- x 1))))))
Induction hypothesis: assume (fact k) works correctly, that is, that the value returned
by the call (fact k) is exactly the factorial of k (written k!)
Induction step: show, using the induction hypothesis, that (fact (+ k 1)) works cor-
rectly. According to the code, (fact (+ k 1)) returns (* (+ k 1) (fact k)). If (fact k)
= k!, as it must by the induction hypothesis, then multiplying it by (+ k 1) certainly
returns (+ k 1)!
(define (new-fact x)
(fact-iter x 0 1))
;; where
We see here the use of an auxiliary function, fact-iter. We should make the
auxiliary function local:
(define (new-fact x)
(define (fact-iter count result)
(if (= count x)
result
(fact-iter (+ count 1) (* (+ count 1) result))))
(fact-iter 0 1))
To show the new program is correct, show that as the program runs, result =
count!
4
3. The meaning of Scheme programs 5
Why? If it holds when the program exits, and if count = x when the program
exits, then the value returned (namely, result) is equal to x! that is, we can use
the relation to show that the program works correctly.
Convince yourself that the new-fact / fact-iter pair require only constant space.
A recursive program which runs in constant space will be said to be tail recur-
sive. Other recursive functions will be said to be properly recursive.
(define (a-plus-abs-b a b)
((if (>= b 0) + -) a b)
In most cases, Scheme uses the “applicative order evaluation”: to evaluate (e1
... em), first evaluate e1, ..., em and then apply the value of e1 to the values of
e2, ..., em.
The intention is that this evaluation rule is inductively defined. At the basis
step, we have those scheme expressions which evaluate to themselves – as, for
example, 7 evaluates to 7 and #t evaluates to #t.
We need to be somewhat careful in the application of this evaluation rule, and
in fact its completely uniform application breaks on ’special forms’, such as if,
cond, define ...
Note, for example, that
5
4. From C++ to Scheme 6
evaluates to 0.
// precondtion: n>=0
int sum_of_squares(int n)
// post: returns 1*1 + 2*2 + ... + n*n
{
int sumsq = 0, i;
//invariant: sumsq = 1*1 + 2*2 + ... + (i-1)*(i-1)
return sumsq;
}
(define (sum_of_squares n)
(define (aux i sumsq)
;; assume sumsq== sum of the first i-1 squares
(cond
((> i n) sumsq) ;; sumq is sum of first n squares
(else (aux (add1 i) (+ (* i i) sumsq)) )
); end cond
); end aux
(aux 1 0))
Note that the first line of cond is the termination condition. The way that
Scheme evaluates cond statements is top-down: the first condition that is true
determines the result. The last line applies aux to the intial values of the
program variables sumsq, i.
For a more complicated example, consider the following program to compute np
by “repeated squaring”.
6
4. From C++ to Scheme 7
(define (pow n p)
(define (aux x k z)
(cond
((= 0 k) z)
((= 1 (remainder k 2) ) (aux (* x x) (quotient k 2) (* z x)))
(else (aux (* x x) (quotient k 2) z ))
); end cond
); end aux
(aux n p 1)
); end pow
You should study this example carefully. The while-loop of the C++ program
is replaced by a tail-recursive definition of the function aux.
Note that the first line of cond is the termination condition. The way that
Scheme evaluates cond statements is top-down: the first condition that is true
determines the result. The last line applies aux to the intial values of the
program variables x,k,z.