Vectors

Vectors

벡터(vector)는 상수 시간 접근과 갱신이 가능한 고정 길이 배열이에요. 벡터의 슬롯들은 0부터 벡터의 슬롯 수보다 하나 작은 값까지 번호가 매겨져요. The Racket Guide의 Vectors 문서에서 벡터를 소개하고 있어요.

두 벡터는 길이가 같고 대응하는 슬롯의 값들이 서로 equal?할 때 equal?해요.

벡터는 가변이거나 불변일 수 있어요. 불변 벡터가 vector-set! 같은 프로시저에 주어지면 exn:fail:contract 예외가 일어나요. 기본 리더(Reading Strings 문서 참고)가 생성한 벡터는 불변이에요. 벡터가 불변인지 확인하려면 immutable?를 사용하세요.

벡터는 단일 값 시퀀스(Sequences 문서 참고)로 사용될 수 있어요. 벡터의 요소들은 시퀀스의 요소로 기능해요. in-vector도 참고하세요.

리터럴 또는 출력된 벡터는 #(로 시작하며, 선택적으로 #( 사이에 숫자가 올 수 있어요. 벡터 읽기에 대한 정보는 Reading Vectors 문서를, 벡터 출력에 대한 정보는 Printing Vectors 문서를 참고하세요.

출처: Racket Reference

본문

(vector? v) → boolean?
v : any/c

procedure

v가 벡터이면 #t, 그렇지 않으면 #f를 돌려줘요.

immutable-vector?mutable-vector?도 참고하세요.

(make-vector size [v]) → vector?
size : exact-nonnegative-integer?
v    : any/c = 0

procedure

size개의 슬롯을 가진 가변 벡터를 돌려주며, 모든 슬롯이 v를 담도록 초기화돼요. v는 모든 요소에 대해 공유되므로, 가변 데이터의 경우 한 요소를 변경하면 다른 요소에도 영향을 미친다는 점에 주의하세요.

> (define v (make-vector 5 2))
> v
'#(2 2 2 2 2)
> (define v (make-vector 5 (box 3)))
> v
'#(#&3 #&3 #&3 #&3 #&3)
> (set-box! (vector-ref v 0) 7)
> v
'#(#&7 #&7 #&7 #&7 #&7)

이 함수는 size에 비례하는 시간이 걸려요.

make-vector로 중첩 벡터를 만드는 것은 흔한 실수예요. v가 모든 요소에 대해 공유된다는 사실은 예를 들어 (make-vector 3 (make-vector 4))가 가변 3x4 행렬을 나타내는 좋은 방법이 아니라는 뜻이에요. 단 하나의 가변 벡터가 세 번 공유되기 때문이죠. 다음과 같이 for/vector를 사용하는 것이 의도한 결과를 만들어낼 가능성이 더 높아요. 각 반복에서 (make-vector 4)를 별도로 평가하니까요:

> (for/vector ([i (in-range 3)])
    (make-vector 4))
'#(#(0 0 0 0) #(0 0 0 0) #(0 0 0 0))
(vector v ...) → vector?
v : any/c

procedure

제공된 v들만큼 많은 슬롯을 가진 새로 할당된 가변 벡터를 돌려주며, 슬롯들이 주어진 v들을 순서대로 담도록 초기화돼요.

(vector-immutable v ...) → (and/c vector? immutable?)
v : any/c

procedure

제공된 v들만큼 많은 슬롯을 가진 새로 할당된 불변 벡터를 돌려주며, 슬롯들이 주어진 v들을 순서대로 담아요.

(vector-length vec) → exact-nonnegative-integer?
vec : vector?

procedure

vec의 길이(즉 벡터의 슬롯 수)를 돌려줘요.

이 함수는 상수 시간이 걸려요.

(vector-ref vec pos) → any/c
vec : vector?
pos : exact-nonnegative-integer?

procedure

vecpos 슬롯에 있는 요소를 돌려줘요. 첫 번째 슬롯은 위치 0이고, 마지막 슬롯은 (vector-length vec)보다 하나 작아요.

이 함수는 상수 시간이 걸려요.

(vector-set! vec pos v) → void?
vec : (and/c vector? (not/c immutable?))
pos : exact-nonnegative-integer?
v   : any/c

procedure

vecpos 슬롯이 v를 담도록 갱신해요.

이 함수는 상수 시간이 걸려요.

(vector*-length vec) → exact-nonnegative-integer?
vec : (and/c vector? (not/c impersonator?))

procedure

(vector*-ref vec pos) → any/c
vec : (and/c vector? (not/c impersonator?))
pos : exact-nonnegative-integer?

procedure

(vector*-set! vec pos v) → void?
vec : (and/c vector? (not/c immutable?) (not/c impersonator?))
pos : exact-nonnegative-integer?
v   : any/c

procedure

vector-length, vector-ref, vector-set!과 같지만, impersonator가 아닌 벡터에서만 동작하도록 제한돼요.

base 패키지 6.90.0.15 버전에서 추가되었어요.

(vector-cas! vec pos old-v new-v) → boolean?
vec   : (and/c vector? (not/c immutable?) (not/c impersonator?))
pos   : exact-nonnegative-integer?
old-v : any/c
new-v : any/c

procedure

벡터를 위한 비교-설정(compare and set) 연산이에요. box-cas!를 참고하세요.

base 패키지 6.11.0.2 버전에서 추가되었어요.

(vector->list vec) → list?
vec : vector?

procedure

vec과 같은 길이와 요소를 가진 리스트를 돌려줘요.

이 함수는 vec의 크기에 비례하는 시간이 걸려요.

(list->vector lst) → vector?
lst : list?

procedure

lst와 같은 길이와 요소를 가진 가변 벡터를 돌려줘요.

이 함수는 lst의 길이에 비례하는 시간이 걸려요.

(vector->immutable-vector vec) → (and/c vector? immutable?)
vec : vector?

procedure

vec과 같은 길이와 요소를 가진 불변 벡터를 돌려줘요. vec 자신이 불변이면 그것이 결과로 돌려져요.

vec가 가변일 때 이 함수는 vec의 크기에 비례하는 시간이 걸려요.

(vector-fill! vec v) → void?
vec : (and/c vector? (not/c immutable?))
v   : any/c

procedure

vec의 모든 슬롯이 v를 담도록 변경해요.

이 함수는 vec의 크기에 비례하는 시간이 걸려요.

(vector-copy! dest dest-start src [src-start src-end]) → void?
dest       : (and/c vector? (not/c immutable?))
dest-start : exact-nonnegative-integer?
src        : vector?
src-start  : exact-nonnegative-integer? = 0
src-end    : exact-nonnegative-integer? = (vector-length src)

procedure

destdest-start 위치에서 시작하는 요소들을, srcsrc-start(포함)부터 src-end(제외)까지의 요소들과 일치하도록 변경해요. destsrc 벡터는 같은 벡터일 수 있으며, 그 경우 목적지 영역이 소스 영역과 겹칠 수 있어요. 복사 후의 목적지 요소들은 복사 전의 소스 요소들과 일치해요. dest-start, src-start, src-end 중 어느 하나라도 범위를 벗어나면(벡터의 크기와 소스·목적지 영역을 고려해서) exn:fail:contract 예외가 일어나요.

이 함수는 (- src-end src-start)에 비례하는 시간이 걸려요.

> (define v (vector 'A 'p 'p 'l 'e))
> (vector-copy! v 4 #(y))
> (vector-copy! v 0 v 3 4)
> v
'#(l p p l y)
(vector->values vec [start-pos end-pos]) → any
vec       : vector?
start-pos : exact-nonnegative-integer? = 0
end-pos   : exact-nonnegative-integer? = (vector-length vec)

procedure

end-pos - start-pos개의 값을 돌려주며, 그것들은 vecstart-pos(포함)부터 end-pos(제외)까지의 요소들이에요. start-posend-pos(vector-length vec)보다 크거나 end-posstart-pos보다 작으면 exn:fail:contract 예외가 일어나요.

이 함수는 vec의 크기에 비례하는 시간이 걸려요.

(build-vector n proc) → vector?
n    : exact-nonnegative-integer?
proc : (exact-nonnegative-integer? . -> . any/c)

procedure

proc을 0부터 (sub1 n)까지의 정수들에 순서대로 적용해 n개의 요소를 가진 벡터를 만들어요. vec이 결과 벡터라면 (vector-ref vec i)(proc i)가 만들어낸 값이에요.

> (build-vector 5 add1)
'#(1 2 3 4 5)

Additional Vector Functions

이 절에 문서화된 바인딩들은 racket/vectorracket 라이브러리가 제공하며, racket/base가 제공하는 게 아니에요.

(require racket/vector) ; package: base
(vector-empty? v) → boolean?
v : vector?

procedure

v가 비어 있으면(즉 길이가 0이면) #t, 그렇지 않으면 #f를 돌려줘요.

base 패키지 7.4.0.4 버전에서 추가되었어요.

(vector-set*! vec pos v ... ...) → void?
vec : (and/c vector? (not/c immutable?))
pos : exact-nonnegative-integer?
v   : any/c

procedure

vecpos 슬롯들이 각 v를 담도록 갱신해요. 갱신은 왼쪽에서 진행되므로 나중의 갱신이 이전 갱신을 덮어써요.

(vector-map proc vec ...+) → vector?
proc : procedure?
vec  : vector?

procedure

procvec들의 요소들에 첫 번째 요소부터 마지막 요소까지 적용해요. proc 인자는 제공된 vec들의 수와 같은 수의 인자를 받아들여야 하고, 모든 vec들은 같은 수의 요소를 가져야 해요. 결과는 proc의 각 결과를 순서대로 담은 새 벡터예요.

> (vector-map + #(1 2 3) #(3 4 5))
'#(4 6)
(vector-map! proc vec ...+) → vector?
proc : procedure?
vec  : (and/c vector? (not/c immutable?))

procedure

vector-map과 같지만, proc의 결과가 proc의 인자들이 가져온 인덱스의 첫 번째 vec에 삽입돼요. 결과는 첫 번째 vec이에요.

> (define v (vector 1 2 3 4))
> (vector-map! add1 v)
'#(2 3 4 5)
> v
'#(2 3 4 5)
(vector-append vec ...) → vector?
vec : vector?

procedure

주어진 벡터들의 모든 요소를 순서대로 담은 새 벡터를 만들어요.

> (vector-append #(1 2) #(3 4))
'#(1 2 3 4)
(vector-take vec pos) → vector?
vec : vector?
pos : exact-nonnegative-integer?

procedure

요소들이 vec의 처음 pos개 요소인 새 벡터를 돌려줘요. vecpos개보다 적은 요소를 가지면 exn:fail:contract 예외가 일어나요.

> (vector-take #(1 2 3 4) 2)
'#(1 2)
(vector-take-right vec pos) → vector?
vec : vector?
pos : exact-nonnegative-integer?

procedure

요소들이 vec의 마지막 pos개 요소인 새 벡터를 돌려줘요. vecpos개보다 적은 요소를 가지면 exn:fail:contract 예외가 일어나요.

> (vector-take-right #(1 2 3 4) 2)
'#(3 4)
(vector-drop vec pos) → vector?
vec : vector?
pos : exact-nonnegative-integer?

procedure

요소들이 처음 pos개 요소 뒤의 vec 요소들인 새 벡터를 돌려줘요. vecpos개보다 적은 요소를 가지면 exn:fail:contract 예외가 일어나요.

> (vector-drop #(1 2 3 4) 2)
'#(3 4)
(vector-drop-right vec pos) → vector?
vec : vector?
pos : exact-nonnegative-integer?

procedure

vec의 접두사를 요소로 하되 pos-길이 꼬리를 버린 새 벡터를 돌려줘요. vecpos개보다 적은 요소를 가지면 exn:fail:contract 예외가 일어나요.

> (vector-drop-right #(1 2 3 4) 1)
'#(1 2 3)
> (vector-drop-right #(1 2 3 4) 3)
'#(1)
(vector-split-at vec pos) → vector? vector?
vec : vector?
pos : exact-nonnegative-integer?

procedure

다음과 같은 결과를 돌려줘요:

(values (vector-take vec pos) (vector-drop vec pos))

단, 더 빠를 수 있어요.

> (vector-split-at #(1 2 3 4 5) 2)
'#(1 2)
'#(3 4 5)
(vector-split-at-right vec pos) → vector? vector?
vec : vector?
pos : exact-nonnegative-integer?

procedure

다음과 같은 결과를 돌려줘요:

(values (vector-take-right vec pos) (vector-drop-right vec pos))

단, 더 빠를 수 있어요.

> (vector-split-at-right #(1 2 3 4 5) 2)
'#(1 2 3)
'#(4 5)
(vector-copy vec [start end]) → vector?
vec   : vector?
start : exact-nonnegative-integer? = 0
end   : exact-nonnegative-integer? = (vector-length v)

procedure

(- end start) 크기의 새 벡터를 만들며, vecstart(포함)부터 end(제외)까지의 모든 요소를 담아요.

> (vector-copy #(1 2 3 4))
'#(1 2 3 4)
> (vector-copy #(1 2 3 4) 3)
'#(4)
> (vector-copy #(1 2 3 4) 2 3)
'#(3)
(vector-set/copy vec pos val) → vector?
vec : vector?
pos : exact-nonnegative-integer?
val : any/c

procedure

vec과 같은 내용을 가진 새 벡터를 만들되, val이 인덱스 pos의 요소가 되어요.

> (vector-set/copy #(1 2 3) 2 'x)
'#(x 2 3)
> (vector-set/copy #(1 2 3) 2 'x)
'#(1 2 x)

base 패키지 8.11.1.10 버전에서 추가되었어요.

(vector-extend vec new-size [val]) → vector?
vec      : vector?
new-size : (and/c exact-nonnegative-integer? (>=/c (vector-length vec)))
val      : any/c = 0

procedure

길이 new-size의 새 벡터를 만들며, 접두사는 vec의 요소들로 채워지고 나머지는 val로 채워져요.

> (vector-extend #(1 2 3) 10)
'#(1 2 3 0 0 0 0 0 0 0)
> (vector-extend #(1 2 3) 10 #f)
'#(1 2 3 #f #f #f #f #f #f #f)
> (vector-extend #(1 2 3) 3 #f)
'#(1 2 3)

base 패키지 8.12.0.10 버전에서 추가되었어요.

(vector-filter pred vec) → vector?
pred : procedure?
vec  : vector?

procedure

pred가 참 값을 만들어내는 vec의 요소들을 담은 새 벡터를 돌려줘요. pred 프로시저는 각 요소에 첫 번째부터 마지막까지 적용돼요.

> (vector-filter even? #(1 2 3 4 5 6))
'#(2 4 6)
(vector-filter-not pred vec) → vector?
pred : procedure?
vec  : vector?

procedure

vector-filter와 같지만 pred 술어의 의미가 뒤집혀요: 결과는 pred#f를 돌려주는 모든 항목들의 벡터예요.

> (vector-filter-not even? #(1 2 3 4 5 6))
'#(1 3 5)
(vector-count proc vec ...+) → exact-nonnegative-integer?
proc : procedure?
vec  : vector?

procedure

(병렬로 취해지는) vec들의 요소들 중 proc#f로 평가되지 않는 요소의 수를 돌려줘요.

> (vector-count = #(1 2 3 4 5) #(1 2 3 4 5))
2
> (vector-count = #(1 2 3 4 5) #(5 4 3 2 1))
1
(vector-argmin proc vec) → any/c
proc : (-> any/c real?)
vec  : vector?

procedure

비어 있지 않은 벡터 vec에서 proc의 결과를 최소화하는 첫 번째 요소를 돌려줘요.

> (vector-argmin car #((1 banana) (1 orange)))
'(1 banana)
(vector-argmax proc vec) → any/c
proc : (-> any/c real?)
vec  : vector?

procedure

비어 있지 않은 벡터 vec에서 proc의 결과를 최대화하는 첫 번째 요소를 돌려줘요.

> (vector-argmax car #((3 pears) (3 oranges)))
'(3 pears)
(vector-member v vec [is-equal?]) → (or/c natural-number/c #f)
v        : any/c
vec      : vector?
is-equal? : (-> any/c any/c any/c) = equal?

procedure

is-equal?에 따라 v와 같은 vec의 첫 번째 요소를 찾아요. 그런 요소가 있으면 vec에서 그 요소의 인덱스가 돌려져요. 그렇지 않으면 결과는 #f예요.

> (vector-member 3 (vector 1 2 3 4))
1
> (vector-member 9 (vector 1 2 3 4))
#f
> (vector-member 1.0 (vector 1 2 3 4) =)
0

base 패키지 8.15.0.1 버전에서 변경됨: is-equal? 인자가 추가되었어요.

(vector-memv v vec) → (or/c natural-number/c #f)
v   : any/c
vec : vector?

procedure

vector-member과 같지만 eqv?를 사용해 요소를 찾아요.

> (vector-memv 3 (vector 1 2 3 4))
1
> (vector-memv 9 (vector 1 2 3 4))
#f
(vector-memq v vec) → (or/c natural-number/c #f)
v   : any/c
vec : vector?

procedure

vector-member과 같지만 eq?를 사용해 요소를 찾아요.

> (vector-memq 3 (vector 1 2 3 4))
1
> (vector-memq 9 (vector 1 2 3 4))
#f
(vector-sort vec less-than? [start end #:key key #:cache-keys? cache-keys?]) → vector?
vec          : vector?
less-than?   : (any/c any/c . -> . any/c)
start        : exact-nonnegative-integer? = 0
end          : (or/c #f exact-nonnegative-integer?) = #f
key          : (or/c #f (any/c . -> . any/c)) = #f
cache-keys?  : boolean? = #f

procedure

sort와 같지만 벡터에 대해 동작해요. vecstart(포함)부터 end(제외)까지의 인덱스에 있는 요소들을 담되 정렬된 순서로 (- end start) 길이의 새 벡터를 돌려줘요 (즉 vec은 수정되지 않아요). 이 정렬은 안정적이에요 (즉 "같은" 요소들의 순서가 보존돼요).

end#f이면 (vector-length vec)으로 대체돼요.

> (define v1 (vector 4 3 2 1))
> (vector-sort v1 <)
'#(4 3 2 1)
> (vector-sort v1 <)
'#(1 2 3 4)
> v1
'#(4 3 2 1)
> (vector-sort v1 < 2 #f #:key #f)
'#(1 2)
> v1
'#(4 3 2 1)
> (define v2 (vector '(4) '(3) '(2) '(1)))
> v2
'#((4) (3) (2) (1))
> (vector-sort v2 < 1 3 #:key car)
'#((2) (3))
> v2
'#((4) (3) (2) (1))

base 패키지 6.6.0.5 버전에서 추가되었어요.

(vector-sort! vec less-than? [start end #:key key #:cache-keys? cache-keys?]) → void?
vec         : (and/c vector? (not/c immutable?))
less-than?  : (any/c any/c . -> . any/c)
start       : exact-nonnegative-integer? = 0
end         : (or/c #f exact-nonnegative-integer?) = #f
key         : (or/c #f (any/c . -> . any/c)) = #f
cache-keys? : boolean? = #f

procedure

vector-sort과 같지만, vecstart(포함)부터 end(제외)까지의 인덱스를 less-than? 프로시저에 따라 정렬해 갱신해요.

> (define v1 (vector 4 3 2 1))
> (vector-sort! v1 <)
> v1
'#(1 2 3 4)
> (define v2 (vector 4 3 2 1))
> v2
'#(4 3 2 1)
> (vector-sort! v2 < 2 #f #:key #f)
> v2
'#(4 3 1 2)
> (define v3 (vector '(4) '(3) '(2) '(1)))
> v3
'#((4) (3) (2) (1))
> (vector-sort! v3 < 1 3 #:key car)
> v3
'#((4) (2) (3) (1))

base 패키지 6.6.0.5 버전에서 추가되었어요.

(vector*-copy vec [start end]) → vector?
vec   : (and/c vector? (not/c impersonator?))
start : exact-nonnegative-integer? = 0
end   : exact-nonnegative-integer? = (vector-length v)

procedure

(vector*-append vec ...) → vector?
vec : (and/c vector? (not/c impersonator?))

procedure

(vector*-set/copy vec pos val) → vector?
vec : (and/c vector? (not/c impersonator?))
pos : exact-nonnegative-integer?
val : any/c

procedure

(vector*-extend vec pos [val]) → vector?
vec : (and/c vector? (not/c impersonator?))
pos : exact-nonnegative-integer?
val : any/c = 0

procedure

vector-copy, vector-append, vector-set/copy, vector-extend과 같지만 impersonator가 아닌 벡터에서만 동작하도록 제한돼요.

base 패키지 8.11.1.10 버전에서 추가되었어요. 8.12.0.10 버전에서 변경됨: vector*-extend가 추가되었어요.

더 알아보기