Solutions to exercises from week 3

;;; implement own version of not
(defun my-not (anything)
(if anything
nil
t))

;;; function of two numbers - return the smaller
(defun smaller-of-two (first-number second-number)
(if (< first-number second-number)
first-number
second-number))

;;; function of three numbers - return the smallest
(defun smallest-of-three (first-number second-number third-number)
(if (and (< first-number second-number) (< first-number third-number))
first-number
(if (< second-number third-number)
second-number
third-number)))

;;; same again, but this version is more readable
(defun smallest-of-three (first-number second-number third-number)
(smaller-of-two (smaller-of-two first-number smaller-of-two) third-number))

;;; reverse the function fahrenheit-to-celsius
(defun celsius-to-fahrenheit ()
(format t "~&Please give a value in degrees C: ")
(fahrenheit (float (+ (* celsius 9/5) 32))))
(format t "~&~a degrees C is ~a degrees F.~&" celsius fahrenheit)))

;;; (and foo bar) transforms into (if foo bar nil)
(defun transform-and-with-two-args (form)
(let* ((first-subform (second form)) ; the first subform was the symbol AND
(second-subform (third form)))
(list 'if first-subform second-subform nil)))

;;; (and foo bar baz) transforms into (if foo (if bar baz nil) nil)
(defun transform-and-with-three-args (form)
(let* ((first-subform (second form)) ; the first subform was the symbol AND
(second-subform (third form))
(third-subform (fourth form)))
(list 'if
first-subform
(list 'if second-subform third-subform nil)
nil)))

#|
When considering transformation of (or foo bar) we have to be a
little bit careful.

Consider

(format t "Help!")
t)

Transforming (or foo bar) into
(if foo
foo
bar)

Hint: use let* ...
|#

;;; (or foo bar) transforms into
#|
(let* ((foo-evaluated foo))
(if foo-evaluated
foo-evaluated
bar))
|#
(defun transform-or-with-two-args (form)
(let* ((first-subform (second form))
(second-subform (third form)))
(list 'let*
(list (list 'first-evaluated first-subform))
(list 'if 'first-evaluated 'first-evaluated second-subform))))

;;; (or foo bar baz) transforms into
#|
(let* ((foo-evaluated foo))
(if foo-evaluated
foo-evaluated
(let* ((bar-evaluated bar))
(if bar-evaluated
bar-evaluated
baz))))
|#

;;; this is getting really revolting. there has to be a better way
;;; (and, indeed, there is)
(defun transform-or-with-three-args (form)
(let* ((first-subform (second form))
(second-subform (third form))
(third-subform (fourth form)))
(list 'let*
(list (list 'first-evaluated first-subform))
(list 'if
'first-evaluated
'first-evaluated
(list 'let*
(list (list 'second-evaluated second-subform))
(list 'if
'second-evaluated
'second-evaluated
third-subform))))))

If you have tried the exercises, looked at the solutions and still do not understand what's going on, I am available for consultation at the times advertised on my office door. Bring your code with you in BOTH the following forms:

• Logbook containing printout (nothing handwritten please)
• file on floppy
Nick Levine