(f some-large-compound) = (o stuff1 (o stuff2 ... (f some-compound) ...))if stuff1, stuff2, ... are needed and/or if the difference between some-large-compound and some-compound is needed, we must use an accumulator
if we wish to compute several results at once, in one function, we need
to use several accumulators
We want to simulate a ball as it moves across a table. We first need a data representation for the ball:
(define-struct ball (coord speed)) ;; A ball is (make-ball xy delta-xy) where xy and delta-xy are posn's. (define sample (make-ball (make-posn 30 20) (make-posn +1 -3)))
Now we can define a function that simulates the movement:
;; move : ball num -> ball (define (move a-ball a-time) (local ((define delta (ball-speed a-ball))) (make-ball (posn+ (posn* a-time delta) (ball-coord a-ball)) delta))) (move sample 2) = (make-ball (make-posn 32 14) (make-posn +1 -3))
That is, we create a new representation of the ball, every time we simulate a move. But, does the world really create a new ball or do the ball's properties change? In other words, are the two balls intensionally equal even though their coordinates differ?
If we believe that the ball remains the same, we write an imperative program because it reflects this idea better:
;; move! : ball num -> void ;; Purpose: - ;; Effect: simulate move of a-ball by a-time (define (move a-ball a-time) (local ((define delta (ball-speed a-ball))) (set-ball-coord! a-ball (posn+ (posn* a-time delta) (ball-coord a-ball))))) (define sample (make-ball (make-posn 32 14) (make-posn +1 -3))) (move sample 2) = (void) ;;; + change
Task: Develop the function move-all, which
;; move-all : (listof ball) num -> void ;; Purpose: - ;; Effect: simulates moving lo-balls for a-time (define (move-all lo-balls a-time) (cond ((empty? lo-balls) a-time) (else (local ((define dummy (move! (first lo-balls a-time)))) (move-all (rest lo-balls) a-time)))))or use begin
;; move-all : (listof ball) num -> void ;; Purpose: - ;; Effect: simulates moving lo-balls for a-time (define (move-all lo-balls a-time) (cond ((empty? lo-balls) a-time) (else (begin ;; throw away the result of the first expression (move! (first lo-balls a-time))) (move-all (rest lo-balls) a-time))))
the list doesn't change
Edit the program!
;; move-all : (listof ball) num -> void ;; Purpose: - ;; Effect: simulates moving lo-balls for a-time (define (move-all lo-balls a-time) (map (lambda (a-ball) (move! a-ball a-time)) lo-balls))This is almost correct but it would return (listof void) instead of (void). What to do? Use for-each:
map : (X -> Y) (listof X) -> (listof Y) ;; create a list of Y's from a list of X'x by applying a function to each ;; of them for-each : (X -> void) (listof X) -> void ;; modify a list of X's by applying a function to each of them; no result
Matthias Felleisen | This page was generated on Mon Apr 12 15:23:18 CDT 1999. |