Eric Normand Newsletter 470: Worked Example: Days of the week

Reflections 🤔

Worked Example: Days of the week

In this issue, I'd like to explore the simple abstraction of mapping the days of the week to the numbers 0-6. Note that this will be a rather theoretical treatment since I'm still exploring the ideas.

Weekdays map to
numbers

Our computers give us an abstraction so solid that we usually forget that it is one: Mapping from bit strings (concrete domain) to integers (abstract domain). It is not completely solid, though. It breaks down when the numbers get large. However, we can put the abstraction out of our minds because we only need seven numbers. The numbers will never get big enough to overflow.

Bitstrings to
numbers

Because we have that solid abstraction, we can securely map our domain concepts onto numbers. I've mentioned in previous issues that you can map the days of the week onto the numbers 0-6. We map days to numbers and numbers to bit strings. Hurray! We can store days of the week in RAM.

Weekdays map to
numbers

Operations

Operations help constrain the myriad choices we can make in how we abstract. We want to ask questions like, "What is the day three days after Friday?" We map days to numbers because we can conveniently define our operations in terms of arithmetic.

(defn domain-operation [args] ;; signatures are in domain terms
   (body ...)) ;; body is in terms of mapping

For instance, we could tell if two days were the same by using equality. In this abstraction, equality is equivalent in the concrete and abstract domains:

(defn days-equal? [a b]
  (= a b))

Likewise, calculating 3 days after a Monday uses addition:

(defn days-after [weekday days]
  (+ weekday days))

;; 0 is Monday
(days-after 0 3) ;;=> 3

It's all a theoretical exercise until you have use cases. We chose numbers because our use c ases neatly mapped to arithmetical addition. Those use cases constrain the problem and make the decision easier.

What about going over 6?

We are mapping days of the week to the numbers 0-6. But we are also doing addition. What happens if we add to a number and the result is over 6? We call the mapping from integers to weekdays a partial function because some integers do not map to any day of the week. There are many ways to deal with that. We'll deal with partial mappings in a future issue. For now, we will use the mod (modulus) operator:

(defn days-after [weekday days]
  (mod (+ weekday days) 7))

Explicit mapping

We can do one more thing and define an explicit mapping. Tuesday is an abstract concept. You can't touch Tuesday. However, the name of the concept (the word Tuesday) is quite concrete, and our brains do the mapping for us. We can map between strings of the names and the numbers that the weekdays map to:

Weekday names

(defn day-name->int [name]
  (get {"Monday" 0 "Tuesday" 1 "Wednesday" 2 "Thursday" 3 "Friday" 4 "Saturday"
5 "Sunday" 6} name))

And we can map back the other way:

(defn day-int->name [n]
  (get ["Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"]
n))

This explicit mapping should allow us to do something like this:

(-> "Monday"
  (day-name->int)
  (days-after 3)
  (day-int->name)) ;=> "Thursday"

We map the name into numbers, where arithmetic is easy, do the arithmetic, then map it back to a name. Expressions like this make me realize that we could easily map the name to other "spaces" where different operations are easy. We often get stuck trying to find a single representation that works in all use cases.

Conclusions

Very many ideas came to the surface by working through this example. We defined our mapping, used use cases to constrain our design, dealt with incomplete mappings (non-total functions), and made some explicit mappings. This exercise was fun. I hope to explore more ideas in this vein in the hopes of eventually writing a book.

Clojure Show 🍿

The Clouncil is a newish Clojure show, specifically aimed at beginners. Check it out!

Grokking Simplicity 📘

I'm happy to see that people are still finding my book:

Just got my paper copy of the "Grokking Simplicity" by @ericnormand.
Can't wait to read it. Been trying to learn functional for a while. I
have high hopes!--Jim
Nanney

You can order the book on Amazon. Please leave a rating and/or review. Reviews are a primary signal that Amazon uses to promote the book. They help others learn whether the book is for them.

You can order the print and/or eBook versions on Manning.com (use TSSIMPLICITY for 50% off).

Clojure Challenge 🤔

Last challenge

Issue 469 - Lazy Fibonacci Sequence

Submissions

This week's challenge

Reverse words

Write a function that takes a string containing words (one or more sentences) and returns a string containing the words in reverse order.

Examples

(reverse-words "my name is Eric.") ;;=> "Eric. is my name"
(reverse-words "hello") ;;=> "hello"
(reverse-words "I love you") ;;=> "you love I"

Note: Words are characters separated by whitespace.

Thanks to this site for the problem idea, where it is rated Very Hard in Java. The problem has been modified.

Please submit your solutions as comments on this gist.

Rock on!
Eric Normand