Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reduce-while function in clojure?

Tags:

clojure

I am new to Clojure programming, and would like to know what is the idiomatic way to do the following thing:

  1. I would like to sum a collection of numbers nums, which may contains a large number of numbers, let's assume there are only positive numbers.

  2. I don't care the exact sum if the sum is very large. For example, if the sum of the numbers is larger than 9999, I would simply return 10000 without summing the remaining numbers at all.

If I implement it with some OO language such as Java, I may do it like below:

private int sum(int[] nums) {
  int sum = 0;
  for(int n : nums) {
    if(sum > 9999) {
      sum = 10000;
      break;
    } else {
      sum += n;
    }
  }
  return sum;
}

A naive implementation in Clojure may look like:

(let [sum (reduce + nums)]
   (if (> sum 9999) 10000 sum))

However, this seems to waste some CPU resource to sum the entire collection of numbers, which is not desired. I am looking for something like take-while function but for reduce, but cannot find it. Is there something like:

(reduce-while pred f val coll)

Or is there any other Clojure idiomatic way to solve this problem? I think the solution can be applied to a set of problems requiring similar logic.

Any comment is appreciated. Thanks.

like image 938
nybon Avatar asked Dec 05 '13 08:12

nybon


1 Answers

If you're using Clojure 1.5.x then you may take advantage of new reduced function:

(reduce #(if (> %1 9999) (reduced 10000) (+ %1 %2)) nums)
like image 92
Leonid Beschastny Avatar answered Nov 06 '22 06:11

Leonid Beschastny