[racket] Mutation of structure elements

From: Gregory Woodhouse (gregwoodhouse at icloud.com)
Date: Wed Oct 31 19:12:01 EDT 2012

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?


Posted on the users mailing list.