这些嵌套向量是如何连接的?

How are these nested vectors connected?

我写了一段代码,它创建了一个向量 'scoreboard',其中包含 3 个大小为 3 的独立向量,所有向量都包含符号 ?在所有指数 0-2。当我现在在记分牌的第一个向量上执行 'vector-set!' 时,要将其第一个元素更改为 'X,向量 2 和 3 也会发生变化。这是怎么发生的?

(define scoreboard (make-vector 3 (make-vector 3 '?)))
(define (display-scoreboard)
(display (vector-ref scoreboard 0))
(newline)
(display (vector-ref scoreboard 1))
(newline)
(display (vector-ref scoreboard 2))
(newline))

(define (X! pos)
(cond
((>= 3 pos) (vector-set! (vector-ref scoreboard 0) (- pos 1) 'X))
))

(display-scoreboard)
(X! 1)
(newline)
(display-scoreboard)

输出:

#(? ? ?)
#(? ? ?)
#(? ? ?)

#(X ? ?)
#(X ? ?)
#(X ? ?)

期望的输出:

#(? ? ?)
#(? ? ?)
#(? ? ?)

#(X ? ?)
#(? ? ?)
#(? ? ?)

图像显示(make-vector 3 (make-vector 3 '()))创建了一个向量 在所有三个插槽中具有相同的行(向量)。

改为 (vector (vector '() '() '()) (vector '() '() '()) (vector '() '() '()))。 或者做一个小辅助函数:

(define (make-row) (vector '() '() '()))
(vector (make-row) (make-row) (make-row))

除了@soegaard 的出色回答之外,我想指出的是,创建向量的 non-shared 向量的惯用方法是使用 build-vector.

;; ignore i and j since we want all elements to be the same
> (define table (build-vector 3 (lambda (i) (build-vector 3 (lambda (j) '?)))))
> table
'#(#(? ? ?) #(? ? ?) #(? ? ?))
;; this will mutate only one row
> (vector-set! (vector-ref table 0) 0 42)
> table
'#(#(42 ? ?) #(? ? ?) #(? ? ?))
;; we can use i and j to make different elements for each index
> (build-vector 3 (lambda (i) (build-vector 3 (lambda (j) (* (add1 i) (add1 j))))))
'#(#(1 2 3) #(2 4 6) #(3 6 9))