2

This is a question about how to properly collect the results from a nested for loop in Clojure. Suppose you want to create a sequence of all vectors [i j] where 0<=j<i<4

The following code

(for [i (range 1 4)] 
  (for [j (range i)] 
     [i j]
  )
)

produces

(([1 0]) ([2 0] [2 1]) ([3 0] [3 1] [3 2]))

but what I really want to get is

([1 0] [2 0] [2 1] [3 0] [3 1] [3 2])

What is the right way to do this?

Notice that I'm not interested in this specific sequence. My purpose here is to learn how to collect results from a nested for loop, which I need for a more complex problem.

Adi Levin
  • 5,165
  • 1
  • 17
  • 26
  • FYI `for` in Clojure is not like `for` in C or Java. Having a for nested in an other for is rather unusual. Clojure `for` is a list comprehension function, it helps you create a list. See Python list comprehension for [exemples](http://carlgroner.me/Python/2011/11/09/An-Introduction-to-List-Comprehensions-in-Python.html). – kawas44 Feb 02 '16 at 08:29
  • Thanks. I tried the approach you are suggesting and it it really cleaner. – Adi Levin Feb 02 '16 at 08:30

2 Answers2

6

Don't nest two loops, rather use one loop with two iterators:

(for [i (range 1 4)
      j (range i)] 
   [i j])
Oin
  • 6,951
  • 2
  • 31
  • 55
3

Assuming you have to use nested for loops, apply concat is the preferred way to flatten a sequence by one level

=> (apply concat 
         (for [i (range 1 4)] 
           (for [j (range i)] 
             [i j])))

([1 0] [2 0] [2 1] [3 0] [3 1] [3 2])

@Oin's solution is always preferable, unless the inner loop depends on the outer loop.

Community
  • 1
  • 1
munk
  • 12,340
  • 8
  • 51
  • 71