Tim Hawes
12/26/2015 1:43:00 AM
On Friday, December 25, 2015 at 7:44:47 PM UTC-5, informatimago wrote:
> informatimago writes:
> Ok. There's a bug in enter-tip-rate:
>
> Since tip-rate is initialized to NIL, the compiler can generate code to
> skip over the while test the first time. Then tip-rate is set to a
> NIL or a real returned by PARSE-FLOAT. If it's not NIL, then (WHEN
> tip-rate (LOOP-FINISH)) will finish the loop, so FORMAT is only called
> when tip-rate is NIL, and then the :WHILE test is always true.
>
> (when tip-rate (loop-finish))
>
> should be:
>
> (when (and tip-rate (minusp tip-rate)) (loop-finish))
>
> and then we don't need :WHILE. So we can as well revert to a simple
> loop:
>
> (defun enter-tip-rate ()
> "Enter tip rate."
> (let ((tip-rate nil))
> (loop
> (let ((line (prompt-read "Enter the tip rate (without the %, default is 15)")))
> (when (zerop (length (string-trim #(#\space #\tab) line)))
> (setf tip-rate 15)
> (return))
> (setf tip-rate (parse-float line))
> (when (and tip-rate (minusp tip-rate))
> (return))
> (format t "That is not a valid amount! Digits only, please.~%")))
> (/ tip-rate 100.0)))
>
> Sorry for the confusion.
Bingo! Except that I wanting to prevent the use from entering a negative number, so I changed the when to an if, like so:
(if (and tip-rate (minusp tip-rate))
(format t "That is not a valid amount! Digits only, please.~%")
(return))
and now it works!
Although your explanation is clear, I am a lil' baffled on why the compiler was "over-achieving" on this. Looking for that ol' adage: the take away from this lesson that will help me remember not to code the problem the way I had. Any advice?
I guess for one, I did not need to put all my checks in up front at the top of the loop.
Anyways, even if you don't have anything to add, thank you so much for your help!