This message is two replies in one.
On Tue, Jul 24, 2007 at 12:26:48AM -0500, Ivan Salazar wrote:
2007/7/23, Carl c.groner@gmail.com:
Wow, no takers, huh. With all the talk that has been going around about lisp lately, this list is surprisingly quiet.
Carl,
I didn't get your email and can't find it in my spam folder. Bummer. But I did find it in the archive:
(defun date-to-time (date &key (tz nil)) "Convert date to timestamp. Date expected to be formatted as: Sat Jul 20 2007 , using 3 letter abbreviations for day of week and month" (let* ((date-list (read-from-string (concatenate 'string "(" date ")"))) (utime (encode-universal-time 0 0 0 (caddr date-list) (+ (position (cadr date-list) '(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)) 1) (cadddr date-list) tz))) (if (equal (seventh (multiple-value-list (decode-universal-time utime))) (position (car date-list) '(Mon Tue Wed Thu Fri Sat Sun))) utime (error "Supplied day (~S) does not match calculated day of week for ~S)" (first date-list) (rest date-list) ))))
(defun days-diff (start end) "Calculate difference in days between the two provided dates. Dates must be in the form accepted by date-to-time" (/ (- (date-to-time end) (date-to-time start)) 60 60 24))
---- end ---
CL-USER> (days-diff "Wed Oct 16 2002" "Wed Oct 23 2002") 7 CL-USER> (days-diff "Wed Oct 16 2002" "Tue Oct 16 2001") -365 CL-USER> (days-diff "Thu Jul 19 2007" "Mon Jul 23 2007") 4
Comments or suggestions welcome.
Your solution seems quite workable, and certainly does the job. I like the way you split the string into lists of atoms using read-from-string. I've seen that idiom before, but forgot about it. I used split-sequence in my solution.
Suggestions: o Instead of cadr, caddr, and cadddr, use second, third, and fourth. o Instead of embedding the lists of months and days, use a separately defined constant. (On the other hand, this is a style issue and quite debatable, especially for such a small, throw-away problem.) o Instead of (seventh (multiple-value-list ...)) use nth-value. (I did the same thing at first, though. :)
Thanks for posting! Remember to put [SPOILER] in your subject when you include a solution.
Ivan said:
Uhm... I liked your solution, even though I'm a newbie. Thanks for submitting it, you helped me to learn some new functions. And yes, almost no-one is trying to solve the quiz (me included) but
^^^^^^ fixed
at least reading the few solutions of others is helping me a lot.
Well, all we *really* know is that no-one is submitting solutions. :) I worked up a solution shortly after I posted the problem, but then wanted to add some more sophisticated condition handling, and I'm not all that familiar with the condition system, so I had to do some reading, and then Life intervened. :)
Off topic: I am reading Paul Graham's ANSI Common Lisp and I have a little question: why does he uses a lot (at least until chapter 4) "and" clauses when I think he should use the "when" macro? For example, in this code snip from figure 4.1:
;; This is a binary search algorithm as you may guess. (defun bin-search (obj vec) (let ((len (length vec))) (and (not (zerop len)) ;Here is the and clause that I may change for ;a when (finder obj vec 0 (- len 1)))))
(defun finder (obj vec start end) ...)
I've read that at least three times I think and it seems that there will be more. I know that the and clause gives the desired behavior of returning the last value that satisfies it or the first one that doesn't, but I would have used a when for some of the cases I've read (it is more readable for me, I think). Is he using the and clause for some reason that eludes me or is it just a personal taste?
In many cases I think it's just personal taste, i.e., a style issue like the one I mentioned above.
But maybe not. If you consider the published code as a snapshot of a real application, some method to this madness emerges (maybe). In particular, consider the code over time. Perhaps he started out with
(and (not (zerop len)) (other code) (finder obj vec 0 (- len 1)))
and then deleted the second clause. Maybe he didn't want to change it. Maybe he thought he might, at some later date, have to add some more code in the middle. Once you shift back and forth between
(when (foo) (baz))
and
(when (and (foo) (bar)) (baz))
enough times, you start to want to skip the middle man and just go for
(and (foo) (baz))
every time, in case you have to add the middle (bar) later.
Or so it seems to me, anyway. :)
I haven't really thought about it all that much, but I might use the following rule of thumb: Start out with
(when (foo) (baz))
The first time you have to change it to
(when (and (foo) (bar)) (baz))
change it to
(and (foo) (bar) (baz))
instead and leave it that way forever after. If it has changed once, it'll probably change again. :)
-- Larry