Как связаны эти вложенные векторы? - PullRequest
3 голосов
/ 30 июня 2019

Я написал фрагмент кода, который создает вектор «табло», который содержит 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 ? ?)
#(? ? ?)
#(? ? ?)

Ответы [ 2 ]

5 голосов
/ 30 июня 2019

enter image description here

На рисунке показано, что (make-vector 3 (make-vector 3 '())) создает вектор с одинаковой строкой (вектором) во всех трех слотах.

Вместо этого напишите (vector (vector '() '() '()) (vector '() '() '()) (vector '() '() '())). Или сделайте небольшую вспомогательную функцию:

(define (make-row) (vector '() '() '()))
(vector (make-row) (make-row) (make-row))
4 голосов
/ 30 июня 2019

В дополнение к отличному ответу @ soegaard, я хочу отметить, что идиоматический способ создания не-общего вектора векторов использует 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))
...