fix vector-map! to not mutate immutable vectors

This commit is contained in:
Matthew Flatt 2014-05-07 07:40:06 -06:00
parent c33707329c
commit 903e82731e
3 changed files with 15 additions and 14 deletions

View File

@ -178,19 +178,15 @@ Applies @racket[proc] to the elements of the @racket[vec]s from the
(vector-map + #(1 2) #(3 4))]
}
@defproc[(vector-map! [proc procedure?] [vec vector?] ...+)
@defproc[(vector-map! [proc procedure?] [vec (and/c vector? (not/c immutable?))] ...+)
vector?]{
Applies @racket[proc] to the elements of the @racket[vec]s from the
first elements to the last. The @racket[proc] argument must accept
the same number of arguments as the number of supplied @racket[vec]s,
and all @racket[vec]s must have the same number of elements. The
each result of @racket[proc] is inserted into the first @racket[vec]
at the index that the arguments to @racket[proc] was taken from. The
result is the first @racket[vec].
Like @racket[vector-map], but result of @racket[proc] is inserted into
the first @racket[vec] at the index that the arguments to
@racket[proc] were taken from. The result is the first @racket[vec].
@mz-examples[#:eval vec-eval
(define v #(1 2 3 4))
(define v (vector 1 2 3 4))
(vector-map! add1 v)
v
]}

View File

@ -221,6 +221,7 @@
(let ([vec (vector 1 -2 -3)])
(test #(1 2 3) vector-map! (lambda (x y) (max x y)) vec #(0 2 3))
(test #(1 2 3) values vec))
(err/rt-test (vector-map! add1 #(1)))
(err/rt-test (vector-map 1 #()) (check-regs #rx"vector-map" #rx"procedure"))
(err/rt-test (vector-map (lambda (x) x) 1) (check-regs #rx"vector-map" #rx"vector"))
(err/rt-test (vector-map (lambda (x) x) #() 1) (check-regs #rx"vector-map" #rx"vector"))

View File

@ -55,11 +55,15 @@
;; that `v' and all the `vs' have the same length
;; and that `f' takes |v + vs| args
;; uses name for error reporting
(define (varargs-check f v vs name)
(define (varargs-check f v vs name need-mutable?)
(unless (procedure? f)
(apply raise-argument-error name "procedure?" 0 f v vs))
(unless (vector? v)
(apply raise-argument-error name "vector?" 1 f v vs))
(unless (and (vector? v)
(or (not need-mutable?)
(not (immutable? v))))
(apply raise-argument-error name
(if need-mutable? "(and/c vector? (not/c immutable?))" "vector?")
1 f v vs))
(let ([len (unsafe-vector-length v)])
(for ([e (in-list vs)]
[i (in-naturals 2)])
@ -86,13 +90,13 @@
len))
(define (vector-map f v . vs)
(let* ([len (varargs-check f v vs 'vector-map)]
(let* ([len (varargs-check f v vs 'vector-map #f)]
[new-v (make-vector len)])
(vector-map/update f new-v len (cons v vs))
new-v))
(define (vector-map! f v . vs)
(define len (varargs-check f v vs 'vector-map!))
(define len (varargs-check f v vs 'vector-map! #t))
(vector-map/update f v len (cons v vs))
v)