I’ll regularly take a JavaScript problem and work it out in ClojureScript. This will hopefully take away some of the Magic™ of functional programming and show how to solve real problems. I promise you won’t have to learn what a monad is.

Problem

Write a function that takes a list of pairs and classifies them as valid or invalid. Pairs are valid if the age is over 35 and the signature is true.

Example input:

[[18, true],[45, true],[61, false],[37, false],[21, false],[78, true]]

For example:

valid([[18, true],[45, true],[61, false],[37, false],[21, false],[78, true]]) ===
  ["Invalid", "Valid", "Invalid", "Invalid", "Invalid", "Valid"]

Solutions

;;#cljs
(defn valid? [data]
  (map (fn [[age signed?]]
         (if (and (> age 35) signed?)
           "Valid"
           "Invalid"))
       data))

Thoughts

Mostly straightforward:

  • We destructure each age/signed? pair. Such destructuring is a normal occurrence.
  • We return a lazy sequence via map. We could do something like “get the first three ‘Valid’” and the calculations would stop as soon as we found them.

This is clearly a tutorial type problem, but I suggest getting into the habit of using more descriptive data structures:

;;#cljs
(defn valid? [data]
  (map (fn [{:keys [:age :signed?] :as person}]
         (assoc person :valid? (and (> age 35) signed?)))
       data))

(valid? [{:age 18 :signed? true}
         {:age 45 :signed? true}
         {:age 61 :signed? false}
         {:age 37 :signed? false}
         {:age 21 :signed? false}
         {:age 78 :signed? true}])
=> ({:age 18 :signed? true :valid? false}
    {:age 45 :signed? true :valid? true}
    {:age 61 :signed? false :valid? false}
    {:age 37 :signed? false :valid? false}
    {:age 21 :signed? false :valid? false}
    {:age 78 :signed? true :valid? true})

I’m partially anticipating that this function will be part of a larger data-flow, so the return is transformed data instead of just the valid? data apart from the context.

Get access to new content

New posts are at bostonou.com. Go check it out, or you can just subscribe from here.

    Reminder: You're subscribing to bostonou.com