Question

Please consider this block of code.

(loop [k from res '()]
    (if (< (count res) n)
      (recur (next-num k)  (conj res (next-num k)))
      (sort res)))

Now, suppose the function, (next-num k), does some expensive computation. We can't afford to call that twice. What will be the alternative? I'm new to Clojure, and don't know many basic features. But I'm sure there must be a way.

Was it helpful?

Solution

Use let:

(loop [k from res '()]
    (if (< (count res) n)
      (let [the-next-num (next-num k)]
          (recur the-next-num  (conj res the-next-num)))
      (sort res)))

OTHER TIPS

Like @NathanDavis said, let allows you to name intermediate values:

(loop [k from res '()]
  (if (< (count res) n)
    (let [next-k (next-num k)]
      (recur next-k (conj res next-k)))
    (sort res)))

However, before reaching for a loop, it's worth seeing if you can compose core functions to the same effect. Often, you can write something less complex and expose the important details.

The meat of the code concerns building up a sequence of repeated applications of next-num. Luckily enough, there's a core function that does this: iterate. Using iterate, we can create an infinite lazy sequence of values:

(iterate next-num from)
; => (from, from', from'', ...)

However, we don't want the first of these values. We can obtain the rest of the sequence with, well, rest:

(rest
  (iterate next-num from))
; => (from', from'', from''', ...)

At this point, we can grab n values with take:

(take n
  (rest
    (iterate next-num from)))
; => (from', from'', from''')

And finally, we can sort these n values:

(sort
  (take n
    (rest
      (iterate next-num from))))
 ; => (from'', from', from''')

Of course, deeply nesting function calls soon becomes awkward. The threading macro ->> (like its brother ->) is a bit of syntactic sugar that lets us rearrange our code into something a little nicer:

(->>
  (iterate next-num from)
  rest
  (take n)
  sort)

So, you can see how a powerful library of sequence-manipulating functions lets us move away from low-level looping.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top