Tags:
In a dinner conversation, my youngest daughter was curious about how many days had she lived so far. I told her that it is easy to calculate for a baby but not for her, though I could easily implement it.
She was still curious, but when I told her that I'm more than 1000 <strike>years</strike> days old (she guessed a bit more than 10), excited, they asked me to implement right away!
Am I getting old ?
I decided to implement in python my first version. Very expressive language. And this was my first version.
def show(name, y, m, d):
cur = datetime.now()
dt = datetime(y, m, d)
dty = datetime(cur.year, m, d)
if dty > cur:
dty = datetime(cur.year-1, m, d)
print( name )
print( ' ', cur-dt )
print( ' ', (cur.year-y), 'years', cur-dty )
print( '------------------------------' )
And it did the trick. After that, I decided to play a bit and implemented in hy-lang, a lisp flavoured python. That was the version
(defn show-age [name y m d]
(setv cur (datetime.now))
(setv dt (datetime y m d))
(setv dty (datetime cur.year m d))
(cond
[(> dty cur) (setv dty (datetime (- cur.year 1) m d))])
(print name)
(print " " (- cur dt))
(print " " (- cur.year y) "years" (- cur dty))
(print "------------------------------"))
Well, it actually looks quite good. Super expressive and succint as the python version, but without the annoying indenting as block delimiter. Specially annoying when different editors use different configs. This is a better python, actually.
Let's stop with polemic conversations.
I decided then, to implement in a more lisp-like language. Let's see the Racket version. First of all, this sequential lisp is not very lispy, therefore I had to break up and better organize my code.
I needed the functions (extracted from the previous code)
(define (diff-dates f s)
(- (->jdn s) (->jdn f)))
(define (how-old-days bday cur-date)
(diff-dates bday cur-date))
(define (get-last-bday bday cur-date)
(let ([last-bday
(date (->year cur-date) (->month bday) (->day bday))])
(if (date>? last-bday cur-date)
(date (- (->year cur-date) 1) (->month bday) (->day bday))
last-bday))
)
(define (how-old-year bday last-bday cur-date)
(list
(- (->year last-bday) (->year bday))
(diff-dates last-bday cur-date)
)
)
(define (show-age name y m d)
(let* (
[bday (date y m d)]
[cur-date (->date (now))]
[last-bday (get-last-bday bday cur-date)]
[num-days (how-old-days bday cur-date)]
[year-and-day (how-old-year bday last-bday cur-date)]
)
(begin
(displayln name)
(printf " ~a days\n" num-days)
(printf " ~a years ~a days\n" (car year-and-day) (cadr year-and-day))
(displayln "------------------------------")
)
))
The code is much better and organized. I have to admit that my first python/hy-lang versions are quite readable and quick to implement, but this last version is super clear and nice.
Or maybe I just need to learn how to write better python and hy-lang.
References:
Any comments or questions, compliments ?
Reach me on twitter - @thiedri