;;; 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: ")
(let* ((celsius (read))
(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
(defun ask-for-help-and-return-t ()
(format t "Help!")
t)
(or (ask-for-help-and-return-t) nil)
Transforming (or foo bar) into
(if foo
foo
bar)
would lead to double trouble.
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: