patternMinor
Adding augmented maps to a vector based on regex text grabbing
Viewed 0 times
mapstextaugmentedaddinggrabbingbasedregexvector
Problem
This is my latest brain child for clojure, could it be done with less code, cleaner, or in a more re applicable way? I am at a pretty early stage in my clojure learning so an in depth explanation of how and why my code is faulty would help me get a handle on what I am doing wrong so I do not build bad habits.
That really ugly looking first function takes two arguments a map and a number. The number is added (with a compensation for done starting at 0) to the :name string of the map. The second function condenses the new appendages along side the original into a list. The third section is a call to the second function.
(def next-apendage
#(hash-map :name (clojure.string/replace (:name %1) #"[0-9]" (str (+ 1 %2 (read-string (re-find #"[0-9]" (:name %1))))))))
(defn add-apendages
[times part]
(loop [done 0
final-apendages [part]]
(if (= done times)
final-apendages
(recur
(inc done)
(conj final-apendages
(next-apendage part done))))))
(add-apendages 2 {:name "tentacle-3"})
;;OUTPUT->[{:name "tentacle-3"} {:name "tentacle-4"} {:name "tentacle-5"}]That really ugly looking first function takes two arguments a map and a number. The number is added (with a compensation for done starting at 0) to the :name string of the map. The second function condenses the new appendages along side the original into a list. The third section is a call to the second function.
Solution
Some things that stand out from your code:
My version would look like:
(def next-appendage #())is really(defn next-appendage [part done])
- Do not use anonymous functions except for really really short functions. You next-appendage function is long for Clojure standards.
- Instead of
hash-mapyou can use the map literal directly{:name (clojure.string/replace ,,,}
- Even though it seems cool when you are starting Clojure, one liners are very hard to read. You already know that is "really ugly" :)
- It is unusual to use loop
. Most of the time you can replace it with a simplermap` or similar
- Do not use read-string, unless you know what you are doing
My version would look like:
(defn add-apendages [times part]
(let [ ;; find the prefix and initial number
[_ prefix number-str] (first (re-seq #"(.*)-([0-9]+)$" (:name part)))
;; parse the number, using Java interop
initial-number (Integer/parseInt number-str)]
;; Build the list of results using a simple map operation
(map (fn [n] {:name (str prefix "-" n)})
(range initial-number (+ 1 initial-number times)))))Code Snippets
(defn add-apendages [times part]
(let [ ;; find the prefix and initial number
[_ prefix number-str] (first (re-seq #"(.*)-([0-9]+)$" (:name part)))
;; parse the number, using Java interop
initial-number (Integer/parseInt number-str)]
;; Build the list of results using a simple map operation
(map (fn [n] {:name (str prefix "-" n)})
(range initial-number (+ 1 initial-number times)))))Context
StackExchange Code Review Q#121621, answer score: 3
Revisions (0)
No revisions yet.