[racket] Mutation of structure elements
I've been thinking about whether how to implement matrices in Racket. One obvious option is just to use a vector
;;a matrix with data stored in the vector data
(struct matrix (rows cols [data #:mutable]))
and then entries can be retrieved simply enough
;;return the (i, j)th element of m
;;rows and columns are indexed from 1 (as is customary in mathematics)
(define (matrix-ref m i j)
(let
([r (matrix-rows m)]
[c (matrix-cols m)]
[i1 (sub1 i)]
[j1 (sub1 j)])
(vector-ref
(matrix-data m)
(+ (* i1 c) j1))))
The question is how to go about implementing an operation to update a single entry in the matrix. Of course, I can make data mutable (as above), retrieve the whole vector,
update a copy and then set data to the new vector, but that's a lot of copying. The following seems to work
;;set the (i, j)th entry of m to v (mutator)
(define (matrix-set! m i j v)
(let
([c (matrix-cols m)]
[d (matrix-data m)])
(vector-set! d (+ (* (sub1 i) c) (sub1 j)) v)))
For example,
> (define m (identity-matrix 3))
> (matrix->list m)
'((1 0 0) (0 1 0) (0 0 1))
> (matrix-set! m 2 3 3)
> (matrix->list m)
'((1 0 0) (0 1 3) (0 0 1))
but I'm unsure if Racket guarantees this behavior (in any case, I assume it is not thread-safe).
Is there a preferred way of doing this sort of thing?