How many days have I lived ?

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 years 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)

Counting days in a date range

``````(define (diff-dates f s)
(- (->jdn s) (->jdn f)))

(define (how-old-days bday cur-date)
(diff-dates bday cur-date))
``````

What is the last birthday - to get the number of years

``````(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))
)
``````

How many years and days in a date range

``````(define (how-old-year bday last-bday cur-date)
(list
(- (->year last-bday) (->year bday))
(diff-dates last-bday cur-date)
)
)
``````

And finally, I have to write the results

``````(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