Question

I have code which directly mutates a matrix for performance. Before I mutate it I want to get a complete copy to store in a new symbol, which is then used by the mutation process. Is there anyway that I can copy a Clojure symbol's contents into a new symbol so that the first can be mutated without affecting the second?

Here is one of my failed attempts:

(var mat1 (clatrix/matrix (clatrix/ones 2 2)))
(var mat1)
(intern 'analyzer.core 'mat1 (clatrix/matrix (clatrix/ones 2 2)))
mat1
(intern 'analyzer.core 'mat2 mat1)
mat2
(clatrix/set mat1 0 0 2)
mat1
mat2

And of course, this does not work:

(def mat1 (clatrix/matrix (clatrix/ones 2 2)
(def mat2 mat1)

I also attempted (but not sure if I'm doing it right here anyway):

(def mat1 (clatrix/matrix (clatrix/ones 2 2)
(def mat2 `mat1)

and

(def mat1 (clatrix/matrix (clatrix/ones 2 2))
(def mat2 ~mat1)

and

(def mat1 (clatrix/matrix (clatrix/ones 2 2))
(def mat2 (.dup mat1))

Any ideas?

Update

I have benchmarked the answers presented so far. I'm not sure what the symbol of the lines means. Setup:

(def mat1 (clatrix/ones 1000 1000) ; Creates a 1000x1000 matrix of 1.0 in each element.

From @Mars:

(criterium.core/bench (let [mat2 (clatrix/matrix mat1)]))

benchmark1

From @JoG:

(criterium.core/bench (let [mat2 (read-string (pr-str mat1))]))

benchmark2

For more general cases

@JoG's solution will work for data structures that serialize into strings well. If someone has ideas about how to make a more general solution, please respond, and I will update this.

Was it helpful?

Solution

Just use matrix again:

(require '[clatrix.core :as clatrix])
; nil

(def mat1 (clatrix/matrix [[1 1][1 1]]))
; #'user/mat1

(def mat2 (clatrix/matrix mat1))
; #'user/mat2

mat1
;  A 2x2 matrix
;  -------------
;  1.00e+00  1.00e+00 
;  1.00e+00  1.00e+00 

(clatrix/set mat1 0 0 2)
; #<DoubleMatrix [2.000000, 1.000000; 1.000000, 1.000000]>

mat1
;  A 2x2 matrix
;  -------------
;  2.00e+00  1.00e+00 
;  1.00e+00  1.00e+00 

mat2
;  A 2x2 matrix
;  -------------
;  1.00e+00  1.00e+00 
;  1.00e+00  1.00e+00 

OTHER TIPS

Given the matrix itself is also a clojure datastrucure how about

(def copy (read-string (pr-str original)))

pr-str dumps the data structure as a string, read-string evaluates it back.

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