Reputation: 707
I have these functions:
(def i (atom {})) ;incremented/calculated file stats
(defn updatei [n fic fos]
(swap! i conj {(keyword n)[fic fos]}))
(defn calcfo [fo fi fis]
(if-let [n (get @i fo)] ;find a previous record?
(let [fic (inc (first n)), fos (+ fis (second n))] ;increment the stats
(updatei fo fic fos))
(let [fic 1, fos fis] ;if not then: first calc recorded
(updatei fo fic fos))))
How could I write (updatei fo fic fos) once, instead of having it listed twice in the function? Is there a secret or-let I am unaware of?
-Hypothetical code-
(defn calcfo [fo fi fis]
(if-let [n (get @i fo)] ;find a previous record?
(let [fic (inc (first n)), fos (+ fis (second n))] ;increment the stats
(or-let [fic 1, fos fis] ;if not then: first calc recorded
(updatei fo fic fos)))))
Or am I thinking of this too imperatively versus functionally?
EDIT:
I decided this made the most sense to me:
(defn calcfo [fo fis]
(apply updatei fo
(if-let [[rfc rfos] (get @i fo)] ;find a previous record?
[(inc rfc) (+ rfos fis)] ;increment the stats
[1 fis]) ;if not then: first calc recorded
))
Thanks for the great answers!
Upvotes: 2
Views: 110
Reputation: 26446
A rearrangement might help
(defn calcfo [fo fi fis]
(apply updatei fo
(if-let [n (get @i fo)]
[(inc (first n)), (+ fis (second n))]
[1, fis] )))
Upvotes: 3
Reputation: 9920
What about using an if
and then destructuring? Here's an approach:
(defn calcfo [fo fi fis]
(let [n (get @i fo) ;find a previous record?
[fic fos] (if n
[(-> n first inc) (-> n second (+ fis))] ;increment the stats
[1 fis])] ;if not then: first calc recorded
(updatei fo fic fos)))
The argument fi
doesn't seem to be being used so maybe you could remove it from the argument list.
(defn calcfo [fo fis] ,,,)
The usage of first
and second
could also be avoided with the use of destructuring when binding n
in the let
form:
(defn calcfo [fo fis]
(let [[x y & _] (get @i fo)
[fic fos] (if x [(inc x) (+ fis y)] [1 fis])]
(updatei fo fic fos)))
Upvotes: 3
Reputation: 30445
I think you would sidestep the whole problem and make your code better if you rewrote updatei
, something like:
(defn- safe+ [a b]
(if a (if b (+ a b) a) b))
(defn updatei [n fic fos]
(swap! i update-in [(keyword n)] #(vector (safe+ fic (first %)) (safe+ fos (second %)))))
There may be a better way to write that code, but the basic idea is to use update-in
to either store the new values (if nothing was stored for that key before), or combine them with what is already there.
Upvotes: 2