Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper form for using a 2D array in Clojure and initializing each cell

Tags:

clojure

(Lisp beginner) I need to create a 2D array, and initialize each cell in the array. Each cell is initialized with a function that is based on data in a preceding cell. So the cell as 0,1 will be initialized with the result of a function that uses the data from cell 0,0, and so on.

I was wondering what is the proper clojure idiom for setting up a data structure like this.

like image 486
JPT Avatar asked Mar 03 '11 15:03

JPT


2 Answers

Representation of your array actually depends on you needs of using it, not initializing it. For example, if you have dense matrix, you most probably should use vector of vectors like this:

[[0, 1, 2, 3, 4],
 [5, 6, 7, 8, 9],
 [9, 8, 7, 6, 5],
 [4, 3, 2, 1, 0],
 [0, 1, 2, 3, 4]]

or single vector with some additional info on raw length:

{:length 5
 :data
 [0, 1, 2, 3, 4, 
 5, 6, 7, 8, 9,
 9, 8, 7, 6, 5, 
 4, 3, 2, 1, 0, 
 0, 1, 2, 3, 4]
}

and if you need sparse matrix, you can use hash-maps:

{0 {0 0, 4 4},
 2 {2 7},
 3 {0 4, 2 2}}

(since your 2D array is small and you generate next value based on previous one, I believe first option is better suited for you).

If you are going to make a lot of matrix-specific manipulations (multiplication, decomposition, etc) you may want to use some existing libraries like Incanter.

And as for filling, my proposal is to use transients and store interim results, i.e. (for one-dimensional vector):

(defn make-array [initial-value f length]
  (loop [result (transient []), length-left length, interim-value initial-value]
    (if (= length-left 0)
        (persistent! result)
        (recur (conj! result (f interim-value)) (- length-left 1) (f interim-value))))

Transients will avoid creating new data structure on each new element, and interim value will avoid need in reading previous element from transient structure.

like image 165
ffriend Avatar answered Oct 17 '22 20:10

ffriend


I don't know if this is a bad technique but I've used hash (or usually ordered) maps to specify 2D "arrays". They build up like this:

{ [x y] value ... }

There are cons to this since you have to specify the limits of the array somehow. And probably it's very slow compared to straight vector presentations as described in ffriend's post.

like image 37
mike3996 Avatar answered Oct 17 '22 18:10

mike3996