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?