Idiomatic Clojure

clojure, coding-style

Solution

The two idiomatic tools Clojure that would most improve your code are the `let` and `->` macros.

`let` allows you to build up local bindings incrementally

`->` chains together a series of function calls in a more readable and easier to edit form

(defn process-input
  [input]
  (-> input
      clean-input
      vectorize-input
      numberize-vector
      map-input
      normalize-height
      finalize-input))

(defn map-builder
  "Transforms the vector of waterfalls into a map of waterfalls."
  [waterfall-db vectorized-db]
  (let [key-str (str (first vectorized-db))
        key (->> key-str
                 (re-seq #"[0-9]+")
                 first
                 (str 'waterfall)
                 keyword)
        val (subs key-str (+ 2 (.indexOf key-str ":")))]
    (assoc waterfall-db key val)))

I also took the liberty of making `waterfall-db` an arg to map-builder so it can be used more easily in functional code (perhaps with the help of `swap!`, `reduce` or `update-in`).

Problem

I'm about a week in to Clojure and functional programming in general—all of my background is in OOP. I'd like to take advantage of Clojure's much-tauted legibility and inherent logic, but right now I don't know if I'm doing that successfully and just not wrapping my mind around it completely, or if I really am abusing the language in a bad way. For example: ``` (ns waterfall-quiz.response-parser (:require [clojure.java.io :as io])) (defn process-input [input] (finalize-input (normalize-height (map-input (numberize-vector (vectorize-input (clean-input input))))))) (defn clean-input "Removes extraneous whitespace." [input] (clojure.string/replace input #"\s+" " ")) (defn vectorize-input "Turns input into a vector." [input] (clojure.string/split input #"\s")) (...) ``` I'm very suspicious of the process-input function, which calls all the other functions to format some input. It is referentially transparent, but it seems so brittle—is there a smarter way to chain all of the functions together? Another example: ``` (defn map-builder "Transforms the vector of waterfalls into a map of waterfalls." [vectorized-db] (assoc waterfall-db (keyword (str 'waterfall (first (re-seq #"[0-9]+" (str (first vectorized-db)))))) (subs (str (first vectorized-db)) (+ 2 (.indexOf (str (first vectorized-db)) ":"))))) ``` I was losing track of where I was in the parentheses constantly while writing that function—should it be broken up into smaller functions?

Original source