2
\$\begingroup\$

From SICP:

Exercise 2.2

Consider the problem of representing line segments in a plane. Each segment is represented as a pair of points: a starting point and an ending point. Define a constructor make-segment and selectors start-segment and end-segment that define the representation of segments in terms of points. Furthermore, a point can be represented as a pair of numbers: the x coordinate and the y coordinate. Accordingly, specify a constructor make-point and selectors x-point and y-point that define this representation. Finally, using your selectors and constructors, define a procedure midpoint-segment that takes a line segment as argument and returns its midpoint (the point whose coordinates are the average of the coordinates of the endpoints). To try your procedures, you'll need a way to print points:

(define (print-point p)
 (newline)
 (display "(")
 (display (x-point p))
 (display ",")
 (display (y-point p))
 (display ")"))

I wrote the following solution:

(define (make-segment a b) (cons a b))
(define (start-segment l) (car l))
(define (end-segment l) (cdr l))
(define (make-point x y) (cons x y))
(define (x-point p) (car p))
(define (y-point p) (cdr p))
(define (sum . l) (if (zero? (length l)) 0 (+ (car l) (apply sum (cdr l)))))
(define (average . l) (/ (apply sum l) (length l)))
(define (midpoint seg)
 (make-point (average (x-point (start-segment seg)) 
 (x-point (end-segment seg)))
 (average (y-point (start-segment seg))
 (y-point (end-segment seg)))))
(define (print-point p)
 (newline)
 (display "(")
 (display (x-point p))
 (display ",")
 (display (y-point p))
 (display ")"))
(define seg-1 (make-segment (make-point 3 4)
 (make-point 8 10)))
(print-point (midpoint seg-1))

What do you think?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Apr 1, 2011 at 4:58
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Your definitions of make-segment and make-point can be simply bound to cons; you may do the same for accessors.

(define make-segment cons)
(define start-segment car)
(define end-segment cdr)
(define make-point cons)
(define x-point car)
(define y-point cdr)

Your definition of sum is similar to how + works. You may use + instead in your definition of average.

(define (average . l) (/ (apply + l) (length l)))

Notice the repetition of code in your definition of midpoint--you create a new point out of the averages of each coordinate of the two end-points that describe the line segment. You may abstract out the calculation of averages either by writing your own helper function or by using the built-in map function, like so:

(define point->coordinate-accessors (list x-point y-point))
(define (midpoint seg)
 (apply make-point (map (lambda (point->coordinate)
 (average (point->coordinate (start-segment seg))
 (point->coordinate (end-segment seg))))
 point->coordinate-accessors)))

This definition is general enough to handle midpoint calculation in as many dimensions as handled by make-point and point->coordinate-accessors.

answered Apr 1, 2011 at 19:54
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.