title: Clojure clean up inner reduce
body: <p>I'm trying to calculate factors of a number, given the prime numbers, so for instance:</p>
  
  <pre><code>REPL=&gt; (find-factors 1176 #{2 3 7})
  #{7 24 4 21 1176 294 56 168 196 6 28 588 3 12 2 14 392 98 147 42 8 49 84}
  </code></pre>
  
  <p>I'm using reduce and declaring inner step functions, but it seems like the code could be cleaner.  I appreciate any suggestions on how to make the code more idiomatic.</p>
  
  <pre><code>(defn mul-all [find-for prod-multiples factors]
    (let [step (fn [[prod-multiples factors] mult]
             (let [step2 (fn [[prod-mults factors] mult2]
                 (let [multiple (* mult mult2)]
                     (if (zero? (rem find-for multiple)) 
                       [(into prod-mults [mult mult2 multiple]) (into factors [multiple])] 
                       [(reduce disj prod-mults [mult mult2]) factors])))]   
               (reduce step2 [prod-multiples factors] prod-multiples)))]
  (reduce step [prod-multiples factors] factors)))
  
  (defn find-factors [find-for prime-factors]
    (loop [result (mul-all find-for prime-factors prime-factors)]
      (if (zero? (count (first result)))
       (second result) 
       (recur (mul-all find-for (first result) (second result))))))
  </code></pre>
  
  <p>-------EDIT---------</p>
  
  <p>@A. Webb - Thanks for the code.  I'm used to imperative programming, so I rewrote your example in Groovy to understand what it's doing.  The findFactorsInject() method uses Groovy's inject() method which is equivalent to reduce in Clojure.</p>
  
  <pre><code>static List recurFn(Set a, Integer n, Integer p ) {
      println "a $a n $n p $p"
      if(n%p == 0) {
          a.addAll(a.collect{Integer it -&gt;it*p})
          recurFn(a, (Integer)(n/p), p);
      } else {
          return [a, n]
      }
  }
  
  static findFactors(Integer findFor, Set&lt;Integer&gt; primes) {
      List result = []
      for(Integer prime in primes) {
          if(result.size() == 0) {
              result = recurFn([1] as Set, findFor, prime)
          } else {
              result = recurFn((Set)result[0], (Integer)result[1], prime)
          }
      }
      return result
  }
  
  static findFactorsInject(Integer findFor, Set&lt;Integer&gt; primes) {
      primes.inject ([[1] as Set, findFor], 
          { List accumulate, Integer prime -&gt;  
              recurFn((Set)accumulate[0], (Integer)accumulate[1], prime)  
          })
  }
  static main(args) {
      println findFactors(1176, ( (Set) [2, 3, 7 ] as Set))
      println findFactorsInject(1176, ( (Set) [2, 3, 7 ] as Set))
  }
  </code></pre>