Search code examples
schemeracketsicp

Exercise 1.3 SICP why doesn't it work with 'when'?


#!/usr/bin/env racket
#lang racket/base

;Define a procedure that takes three numbers as arguments and returns the sum of the
;squares of the two larger numbers.

(define (procsq a b c)
  (when (and (< a b)(> c a))(+ (* b b)(* c c))) 
  (when (and (< a c)(> b a))(+ (* b b)(* c c)))
  (when (and (< b a)(> c b))(+ (* a a)(* c c)))
  (when (and (< b c)(> a b))(+ (* a a)(* c c)))
  (when (and (< c a)(> b a))(+ (* a a)(* b b)))
  (when (and (< c b)(> a c))(+ (* a a)(* b b)))) 

(displayln (procsq 1 2 3)); Why does it print #<void> ?
(displayln (procsq 3 2 1))
(displayln (procsq 3 1 2)); Why does it print #<void> ?

I coded my answer using when, why doesn't it work? The comments show with what arguments it doesn't work.


Solution

  • A procedure returns the value of the last expression in the body. Each when is calculating a value, but they're not being returned because it's not the last expression. It then goes to the next when. The result is the value of the last when, which will be #<void> if the condition isn't true.

    Use cond when you have a series of mutually-exclusive conditions, not separate when expressions. It will return the value corresponding to the first condition that's true.

    (define (procsq a b c)
      (cond ((and (< a b)(> c a)) (+ (* b b)(* c c)))
            ((and (< a c)(> b a)) (+ (* b b)(* c c)))
            ((and (< b a)(> c b)) (+ (* a a)(* c c)))
            ((and (< b c)(> a b)) (+ (* a a)(* c c)))
            ((and (< c a)(> b a)) (+ (* a a)(* b b)))
            ((and (< c b)(> a c)) (+ (* a a)(* b b)))))