TL;DR: I want to convert something like ["api.api-key" "api.base-url"] into [[:api :api-key] [:api :base-url]]
I know how to do this:
(def required-keys ["api.api-key" "api.base-url" "foo.bar.baz"])
(defn dot-str-to-vec-keywords [s]
; Splits a string with dot notation and transforms the result into a vector of keywords
(vec (map keyword (clojure.string/split s #"\."))))
(into [] (map dot-str-to-vec-keywords required-keys)) ; [[:api :api-key] [:api :base-url] [:foo :bar :baz]]
(into []
(comp
(map #(clojure.string/split #”\.”)) ; yields a seq of pairs
(map (juxt (comp keyword first)
(comp keyword second)))) ; converts entries to pairs of keywords
required-keys)
Disclaimer: This is written without testing and entirely without a repl available, so it might need some massaging.
The idea is to use transducers to perform first the splitting and keywording in separate steps. Now that I look at it, there are probably prettier ways than using juxt here, but juxt makes it explicit that the expected output is a seq of pairs. Using map instead of juxt in the second step could be viable as well, but would no longer be explicit about the pair structure.
Mostly, except I’d say in your case the use of into [] and wrapping map inside vec isn’t idiomatic, use mapv for both instead. Also, using functions fully qualified isn’t idiomatic, use require with :as instead. Lastly, a comment as doc-string isn’t idiomatic as well, use the doc-string feature of defn instead:
(require '[clojure.string :as str])
(defn dot-str-to-vec-keywords
"Splits a string with dot notation and transforms the result into a vector of keywords"
[s]
(mapv keyword (str/split s #"\.")))
(mapv dot-str-to-vec-keywords required-keys)
And you could also try with threading, I wouldn’t say it is more or less idiomatic, just a different style: