Array changes in response to user feedback (and my personal neuroses)

* `list->array' now accepts an optional shape argument, and always returns
  an immutable array

* `vector->array' now accepts an optional shape argument, and always
  returns a mutable array

* Removed `make-mutable-array' because `vector->array' does its job now (I
  never liked the name anyway)

* Renamed `unsafe-mutable-array' to `unsafe-vector->array'

* Added optional type annotation to `array' macro to match `mutable-array'

* Reworded error messages in array broadcasting functions

* Made minor array doc fixes
This commit is contained in:
Neil Toronto 2012-12-17 15:53:44 -07:00
parent 8c66be33e7
commit b8efd58aca
13 changed files with 150 additions and 104 deletions

View File

@ -21,7 +21,7 @@
(let ([shift (- new-dims old-dims)]) (let ([shift (- new-dims old-dims)])
(cond [(index? shift) shift] (cond [(index? shift) shift]
[else (error 'array-broadcast [else (error 'array-broadcast
"cannot broadcast to lower-dimensional array; given ~e and ~e" "cannot broadcast to a lower-dimensional shape; given ~e and ~e"
arr new-ds)]))) arr new-ds)])))
(define old-js (make-thread-local-indexes old-dims)) (define old-js (make-thread-local-indexes old-dims))
(define old-f (unsafe-array-proc arr)) (define old-f (unsafe-array-proc arr))
@ -95,8 +95,10 @@
(: array-shape-broadcast (case-> ((Listof Indexes) -> Indexes) (: array-shape-broadcast (case-> ((Listof Indexes) -> Indexes)
((Listof Indexes) (U #f #t 'permissive) -> Indexes))) ((Listof Indexes) (U #f #t 'permissive) -> Indexes)))
(define (array-shape-broadcast dss [broadcasting (array-broadcasting)]) (define (array-shape-broadcast dss [broadcasting (array-broadcasting)])
(define (fail) (error 'array-shape-broadcast "incompatible array shapes (broadcasting ~v): ~a" (define (fail) (error 'array-shape-broadcast
broadcasting (string-join (map (λ (ds) (format "~e" ds)) dss) ", "))) "incompatible array shapes (array-broadcasting ~v): ~a"
broadcasting
(string-join (map (λ (ds) (format "~e" ds)) dss) ", ")))
(cond [(empty? dss) #()] (cond [(empty? dss) #()]
[else (for/fold ([new-ds (first dss)]) ([ds (in-list (rest dss))]) [else (for/fold ([new-ds (first dss)]) ([ds (in-list (rest dss))])
(shape-broadcast2 new-ds ds fail broadcasting))])) (shape-broadcast2 new-ds ds fail broadcasting))]))

View File

@ -23,14 +23,14 @@
ds (λ () (raise-argument-error 'name "Indexes" ds)))]) ds (λ () (raise-argument-error 'name "Indexes" ds)))])
(define vs (for/vector #:length (array-shape-size ds) maybe-fill ... (define vs (for/vector #:length (array-shape-size ds) maybe-fill ...
(clause ...) maybe-type ... body ...)) (clause ...) maybe-type ... body ...))
(unsafe-mutable-array ds vs))))] (unsafe-vector->array ds vs))))]
[(_ name:id for/vector:id (clause ...) (~optional (~seq : A:expr)) body:expr ...+) [(_ name:id for/vector:id (clause ...) (~optional (~seq : A:expr)) body:expr ...+)
(with-syntax ([(maybe-type ...) (if (attribute A) #'(: A) #'())]) (with-syntax ([(maybe-type ...) (if (attribute A) #'(: A) #'())])
(syntax/loc stx (syntax/loc stx
(let () (let ()
(define vs (for/vector (clause ...) maybe-type ... body ...)) (define vs (for/vector (clause ...) maybe-type ... body ...))
(define ds ((inst vector Index) (vector-length vs))) (define ds ((inst vector Index) (vector-length vs)))
(unsafe-mutable-array ds vs))))])) (unsafe-vector->array ds vs))))]))
(define-syntax-rule (for/array: e ...) (define-syntax-rule (for/array: e ...)
(base-for/array: for/array: for/vector: e ...)) (base-for/array: for/array: for/vector: e ...))
@ -49,13 +49,13 @@
ds (λ () (raise-argument-error 'name "Indexes" ds)))]) ds (λ () (raise-argument-error 'name "Indexes" ds)))])
(define vs (for/vector #:length (array-shape-size ds) maybe-fill ... (define vs (for/vector #:length (array-shape-size ds) maybe-fill ...
(clause ...) body ...)) (clause ...) body ...))
(unsafe-mutable-array ds vs))))] (unsafe-vector->array ds vs))))]
[(_ name:id for/vector:id (clause ...) body:expr ...+) [(_ name:id for/vector:id (clause ...) body:expr ...+)
(syntax/loc stx (syntax/loc stx
(let () (let ()
(define vs (for/vector (clause ...) body ...)) (define vs (for/vector (clause ...) body ...))
(define ds ((inst vector Index) (vector-length vs))) (define ds ((inst vector Index) (vector-length vs)))
(unsafe-mutable-array ds vs)))])) (unsafe-vector->array ds vs)))]))
(define-syntax-rule (for/array e ...) (define-syntax-rule (for/array e ...)
(base-for/array for/array for/vector e ...)) (base-for/array for/array for/vector e ...))

View File

@ -15,8 +15,6 @@
vector*->array vector*->array
array->list* array->list*
array->vector* array->vector*
list->array
vector->array
array->list array->list
array->vector) array->vector)

View File

@ -37,7 +37,7 @@
(define (parallel-array->mutable-array arr) (define (parallel-array->mutable-array arr)
(define size (array-size arr)) (define size (array-size arr))
(cond (cond
[(zero? size) (unsafe-mutable-array (array-shape arr) (vector))] [(zero? size) (unsafe-vector->array (array-shape arr) (vector))]
[else [else
(define ds (array-shape arr)) (define ds (array-shape arr))
(define dims (vector-length ds)) (define dims (vector-length ds))
@ -61,7 +61,7 @@
(for: ([f (in-list futures)]) (for: ([f (in-list futures)])
(touch f)) (touch f))
(unsafe-mutable-array ds vs))])) (unsafe-vector->array ds vs))]))
(: parallel-array-strict (All (A) ((Array A) -> (Array A)))) (: parallel-array-strict (All (A) ((Array A) -> (Array A))))
(define (parallel-array-strict arr) (define (parallel-array-strict arr)

View File

@ -4,13 +4,18 @@
typed/racket/base typed/racket/base
(for-syntax racket/base syntax/parse) (for-syntax racket/base syntax/parse)
"array-syntax.rkt" "array-syntax.rkt"
(except-in "typed-array-struct.rkt" build-array build-strict-array)) (except-in "typed-array-struct.rkt"
build-array
build-strict-array
list->array))
(require/untyped-contract (require/untyped-contract
(begin (require "typed-array-struct.rkt")) (begin (require "typed-array-struct.rkt"))
"typed-array-struct.rkt" "typed-array-struct.rkt"
[build-array (All (A) ((Vectorof Integer) ((Vectorof Index) -> A) -> (Array A)))] [build-array (All (A) ((Vectorof Integer) ((Vectorof Index) -> A) -> (Array A)))]
[build-strict-array (All (A) ((Vectorof Integer) ((Vectorof Index) -> A) -> (Array A)))]) [build-strict-array (All (A) ((Vectorof Integer) ((Vectorof Index) -> A) -> (Array A)))]
[list->array (All (A) (case-> ((Listof A) -> (Array A))
((Vectorof Integer) (Listof A) -> (Array A))))])
(define-syntax array? (make-rename-transformer #'Array?)) (define-syntax array? (make-rename-transformer #'Array?))
(define-syntax array-shape (make-rename-transformer #'Array-shape)) (define-syntax array-shape (make-rename-transformer #'Array-shape))
@ -27,10 +32,13 @@
array-strict array-strict
array-strict! array-strict!
array-strict? array-strict?
make-unsafe-array-proc
build-array build-array
build-strict-array
list->array
make-unsafe-array-proc
unsafe-build-array unsafe-build-array
unsafe-build-strict-array unsafe-build-strict-array
unsafe-list->array
unsafe-array-proc unsafe-array-proc
array-lazy array-lazy
array array
@ -46,8 +54,11 @@
array-lift-comparison) array-lift-comparison)
(define-syntax (array stx) (define-syntax (array stx)
(syntax-parse stx (syntax-parse stx #:literals (:)
[(_ e:expr) (syntax/loc stx (array/syntax array list flat-list->array e))] [(_ e:expr)
(syntax/loc stx (array/syntax array list unsafe-list->array e))]
[(_ e:expr : T:expr)
(syntax/loc stx (array/syntax array (inst list T) unsafe-list->array e))]
[_:id (raise-syntax-error 'array "not allowed as an expression" stx)])) [_:id (raise-syntax-error 'array "not allowed as an expression" stx)]))
(define-syntax-rule (array-strict arr-expr) (define-syntax-rule (array-strict arr-expr)

View File

@ -1,6 +1,7 @@
#lang racket/base #lang racket/base
(require (for-syntax racket/base)) (require (for-syntax racket/base)
(only-in typed/racket/base inst Index))
(provide array/syntax) (provide array/syntax)
@ -40,4 +41,4 @@
(with-syntax ([(d ...) ds] (with-syntax ([(d ...) ds]
[(v ...) (syntax-vector-flatten #'e)]) [(v ...) (syntax-vector-flatten #'e)])
(syntax/loc stx (syntax/loc stx
(->array (vector d ...) (constr v ...)))))])) (->array ((inst vector Index) d ...) (constr v ...)))))]))

View File

@ -5,20 +5,21 @@
(for-syntax racket/base syntax/parse) (for-syntax racket/base syntax/parse)
"array-syntax.rkt" "array-syntax.rkt"
(except-in "typed-mutable-array.rkt" (except-in "typed-mutable-array.rkt"
make-mutable-array)) vector->array))
(require/untyped-contract (require/untyped-contract
(begin (require "typed-mutable-array.rkt")) (begin (require "typed-mutable-array.rkt"))
"typed-mutable-array.rkt" "typed-mutable-array.rkt"
[make-mutable-array (All (A) ((Vectorof Integer) (Vectorof A) -> (Mutable-Array A)))]) [vector->array (All (A) (case-> ((Vectorof A) -> (Mutable-Array A))
((Vectorof Integer) (Vectorof A) -> (Mutable-Array A))))])
(provide (provide
;; Mutable-Array ;; Mutable-Array
Mutable-Array Mutable-Array
mutable-array? mutable-array?
mutable-array-data mutable-array-data
make-mutable-array vector->array
unsafe-mutable-array unsafe-vector->array
mutable-array-copy mutable-array-copy
mutable-array mutable-array
;; Conversion ;; Conversion
@ -28,7 +29,7 @@
(define-syntax (mutable-array stx) (define-syntax (mutable-array stx)
(syntax-parse stx #:literals (:) (syntax-parse stx #:literals (:)
[(_ e:expr) [(_ e:expr)
(syntax/loc stx (array/syntax mutable-array vector make-mutable-array e))] (syntax/loc stx (array/syntax mutable-array vector unsafe-vector->array e))]
[(_ e:expr : T:expr) [(_ e:expr : T:expr)
(syntax/loc stx (array/syntax mutable-array (inst vector T) make-mutable-array e))] (syntax/loc stx (array/syntax mutable-array (inst vector T) unsafe-vector->array e))]
[_:id (raise-syntax-error 'mutable-array "not allowed as an expression" stx)])) [_:id (raise-syntax-error 'mutable-array "not allowed as an expression" stx)]))

View File

@ -11,14 +11,6 @@
;; Conversion to arrays ;; Conversion to arrays
(make-to-array-functions list*->array vector*->array) (make-to-array-functions list*->array vector*->array)
(: list->array (All (A) ((Listof A) -> (Array A))))
(define (list->array xs)
(vector->array (list->vector xs)))
(: vector->array (All (A) ((Vectorof A) -> (Array A))))
(define (vector->array xs)
(unsafe-mutable-array ((inst vector Index) (vector-length xs)) xs))
(: array->list (All (A) ((Array A) -> (Listof A)))) (: array->list (All (A) ((Array A) -> (Listof A))))
(define (array->list arr) (define (array->list arr)
(vector->list (array->vector arr))) (vector->list (array->vector arr)))

View File

@ -113,12 +113,25 @@
(unsafe-build-strict-array ds (λ: ([js : Indexes]) (unsafe-build-strict-array ds (λ: ([js : Indexes])
(proc (vector->immutable-vector js)))))) (proc (vector->immutable-vector js))))))
(: flat-list->array (All (A) (In-Indexes (Listof A) -> (Array A)))) (: unsafe-list->array (All (A) (Indexes (Listof A) -> (Array A))))
(define (flat-list->array ds lst) (define (unsafe-list->array ds xs)
(let ([ds (check-array-shape ds (λ () (raise-argument-error 'array "(Vectorof Index)" ds)))]) (define vs (list->vector xs))
(define vs (list->vector lst)) (unsafe-build-strict-array
(unsafe-build-strict-array ds (λ: ([js : Indexes]) (unsafe-vector-ref vs (unsafe-array-index->value-index ds js)))))
ds (λ: ([js : Indexes]) (unsafe-vector-ref vs (unsafe-array-index->value-index ds js))))))
(: list->array (All (A) (case-> ((Listof A) -> (Array A))
(In-Indexes (Listof A) -> (Array A)))))
(define list->array
(case-lambda
[(xs) (unsafe-list->array ((inst vector Index) (length xs)) xs)]
[(ds xs)
(let* ([ds (check-array-shape
ds (λ () (raise-argument-error 'list->array "(Vectorof Index)" 0 ds xs)))]
[size (array-shape-size ds)]
[n (length xs)])
(if (= size n)
(unsafe-list->array ds xs)
(raise-argument-error 'list->array (format "List of length ~e" size) 1 ds xs)))]))
(: array-lazy (All (A) ((Array A) -> (Array A)))) (: array-lazy (All (A) ((Array A) -> (Array A))))
(define (array-lazy arr) (define (array-lazy arr)

View File

@ -17,28 +17,33 @@
(define mutable-array? Mutable-Array?) (define mutable-array? Mutable-Array?)
(define mutable-array-data Mutable-Array-data) (define mutable-array-data Mutable-Array-data)
(: unsafe-mutable-array (All (A) (Indexes (Vectorof A) -> (Mutable-Array A)))) (: unsafe-vector->array (All (A) (Indexes (Vectorof A) -> (Mutable-Array A))))
(define (unsafe-mutable-array ds vs) (define (unsafe-vector->array ds vs)
(define proc (make-unsafe-array-proc ds (λ (j) (unsafe-vector-ref vs j)))) (define proc (make-unsafe-array-proc ds (λ (j) (unsafe-vector-ref vs j))))
(define set-proc (make-unsafe-array-set-proc A ds (λ (j v) (unsafe-vector-set! vs j v)))) (define set-proc (make-unsafe-array-set-proc A ds (λ (j v) (unsafe-vector-set! vs j v))))
(Mutable-Array ds (vector-length vs) (box #t) void proc set-proc vs)) (Mutable-Array ds (vector-length vs) (box #t) void proc set-proc vs))
(: make-mutable-array (All (A) (In-Indexes (Vectorof A) -> (Mutable-Array A)))) (: vector->array (All (A) (case-> ((Vectorof A) -> (Mutable-Array A))
(define (make-mutable-array ds vs) (In-Indexes (Vectorof A) -> (Mutable-Array A)))))
(let* ([ds (check-array-shape (define vector->array
ds (λ () (raise-argument-error 'make-mutable-array "(Vectorof Index)" 0 ds vs)))] (case-lambda
[size (array-shape-size ds)] [(vs) (unsafe-vector->array ((inst vector Index) (vector-length vs)) vs)]
[n (vector-length vs)]) [(ds vs)
(cond [(= size n) (unsafe-mutable-array ds vs)] (let* ([ds (check-array-shape
[else (raise-argument-error 'mutable-array (format "Vector of length ~e" size) 1 ds vs)]))) ds (λ () (raise-argument-error 'vector->array "(Vectorof Index)" 0 ds vs)))]
[size (array-shape-size ds)]
[n (vector-length vs)])
(if (= size n)
(unsafe-vector->array ds vs)
(raise-argument-error 'vector->array (format "Vector of length ~e" size) 1 ds vs)))]))
(: mutable-array-copy (All (A) ((Mutable-Array A) -> (Mutable-Array A)))) (: mutable-array-copy (All (A) ((Mutable-Array A) -> (Mutable-Array A))))
(define (mutable-array-copy arr) (define (mutable-array-copy arr)
(unsafe-mutable-array (array-shape arr) (vector-copy-all (mutable-array-data arr)))) (unsafe-vector->array (array-shape arr) (vector-copy-all (mutable-array-data arr))))
(: flat-vector->matrix : (All (A) (Index Index (Vectorof A) -> (Array A)))) (: flat-vector->matrix : (All (A) (Index Index (Vectorof A) -> (Array A))))
(define (flat-vector->matrix m n v) (define (flat-vector->matrix m n v)
(make-mutable-array (vector m n) v)) (vector->array (vector m n) v))
;; =================================================================================================== ;; ===================================================================================================
;; Conversions ;; Conversions
@ -47,4 +52,4 @@
(define (array->mutable-array arr) (define (array->mutable-array arr)
(define ds (array-shape arr)) (define ds (array-shape arr))
(define g (unsafe-array-proc arr)) (define g (unsafe-array-proc arr))
(unsafe-mutable-array ds (inline-build-array-data ds (λ (js j) (g js)) A))) (unsafe-vector->array ds (inline-build-array-data ds (λ (js j) (g js)) A)))

View File

@ -87,7 +87,7 @@
(cond [(pred? lst) (unsafe-build-strict-array #() (λ (js) lst))] (cond [(pred? lst) (unsafe-build-strict-array #() (λ (js) lst))]
[ds (let ([ds (check-array-shape ds raise-shape-error)]) [ds (let ([ds (check-array-shape ds raise-shape-error)])
(define size (array-shape-size ds)) (define size (array-shape-size ds))
(unsafe-mutable-array ds (list*->flat-vector lst size pred?)))] (unsafe-vector->array ds (list*->flat-vector lst size pred?)))]
[else (raise-shape-error)])) [else (raise-shape-error)]))
(: vector*->array (All (A) ((Vectorof* A) ((Vectorof* A) -> Any : A) -> (Array A)))) (: vector*->array (All (A) ((Vectorof* A) ((Vectorof* A) -> Any : A) -> (Array A))))

View File

@ -24,9 +24,9 @@
@title[#:tag "arrays" #:style 'toc]{Arrays} @title[#:tag "arrays" #:style 'toc]{Arrays}
@(author-neil) @(author-neil)
@bold{Performance Warning:} Most of the array-producing functions exported by @bold{Performance Warning:} Indexing the elements of arrays created in untyped Racket
@racketmodname[math/array] run 25-50 times slower in untyped Racket, due to the is currently 25-50 times slower than doing the same in Typed Racket, due to the overhead
overhead of checking higher-order contracts. We are working on it. of checking higher-order contracts. We are working on it.
For now, if you need speed, use the @racketmodname[typed/racket] language. For now, if you need speed, use the @racketmodname[typed/racket] language.
@ -301,8 +301,8 @@ operations to succeed only if array shapes match exactly:
(array* (index-array #(3 3)) (array 10)))] (array* (index-array #(3 3)) (array 10)))]
Another option is @hyperlink["http://www.r-project.org"]{R}-style permissive broadcasting, Another option is @hyperlink["http://www.r-project.org"]{R}-style permissive broadcasting,
which allows pointwise operations to @italic{always} succeed, by repeating any axis instead which allows pointwise operations to @italic{always} succeed, by repeating shorter axes' rows
of stretching just singleton axes: instead of repeating just singleton axes' rows:
@interaction[#:eval typed-eval @interaction[#:eval typed-eval
(define arr10 (array-map number->string (index-array #(10)))) (define arr10 (array-map number->string (index-array #(10))))
(define arr3 (array-map number->string (index-array #(3)))) (define arr3 (array-map number->string (index-array #(3))))
@ -479,12 +479,14 @@ Returns the vector of data that @racket[arr] contains.
@section{Construction} @section{Construction}
@defform[(array #[#[...] ...])]{ @defform/subs[(array #[#[...] ...] maybe-type-ann)
[(maybe-type-ann (code:line) (code:line : type))]]{
Creates a @tech{strict} @racket[Array] from nested rows of expressions. Creates a @tech{strict} @racket[Array] from nested rows of expressions.
The vector syntax @racket[#[...]] delimits rows. These may be nested to any depth, and must have a The vector syntax @racket[#[...]] delimits rows. These may be nested to any depth, and must have a
rectangular shape. Using square parentheses is not required, but is encouraged to help distinguish rectangular shape. Using square parentheses is not required, but is encouraged to help visually
array contents from array shapes and other vectors. distinguish array contents from array indexes and other vectors.
(See the examples for @racket[indexes-array] for an illustration.)
@examples[#:eval typed-eval @examples[#:eval typed-eval
(array 0) (array 0)
@ -492,13 +494,16 @@ array contents from array shapes and other vectors.
(array #[#[1 2 3] #[4 5 6]]) (array #[#[1 2 3] #[4 5 6]])
(array #[#[1 2 3] #[4 5]])] (array #[#[1 2 3] #[4 5]])]
As with the @racket[list] constructor, the type chosen for the array is the narrowest type As with the @racket[list] constructor, the type chosen for the array is the narrowest type
all the elements can have. Unlike @racket[list], because @racket[array] is syntax, the only way all the elements can have. Unlike @racket[list], because @racket[array] is syntax, instantiating
to change the element type is to annotate the result. @racket[array] with the desired element type is a syntax error:
@interaction[#:eval typed-eval @interaction[#:eval typed-eval
(list 1 2 3) (list 1 2 3)
(array #[1 2 3]) (array #[1 2 3])
((inst list Real) 1 2 3) ((inst list Real) 1 2 3)
((inst array Real) #[1 2 3]) ((inst array Real) #[1 2 3])]
There are two easy ways to annotate the element type:
@interaction[#:eval typed-eval
(array #[1 2 3] : Real)
(ann (array #[1 2 3]) (Array Real))] (ann (array #[1 2 3]) (Array Real))]
Annotating should rarely be necessary because the @racket[Array] type is covariant. Annotating should rarely be necessary because the @racket[Array] type is covariant.
@ -509,6 +514,8 @@ Normally, the datums within literal vectors are implicitly quoted. However, when
(array #[not okay]) (array #[not okay])
(array #['this 'is 'okay]) (array #['this 'is 'okay])
(array #['#(an) '#(array) '#(of) '#(vectors)])] (array #['#(an) '#(array) '#(of) '#(vectors)])]
Another way to create an immutable, strict array from literal data is to use @racket[list->array].
} }
@defform/subs[(mutable-array #[#[...] ...] maybe-type-ann) @defform/subs[(mutable-array #[#[...] ...] maybe-type-ann)
@ -528,6 +535,8 @@ the array's elements:
arr arr
(array-set! arr #(0) 10.0) (array-set! arr #(0) 10.0)
arr] arr]
Another way to create a mutable array from literal data is to use @racket[vector->array].
} }
@defproc[(make-array [ds In-Indexes] [value A]) (Array A)]{ @defproc[(make-array [ds In-Indexes] [value A]) (Array A)]{
@ -586,16 +595,6 @@ Printing a lazy array computes and caches all of its elements, as does applying
@racket[array-strict!] to it. @racket[array-strict!] to it.
} }
@defproc[(make-mutable-array [ds In-Indexes] [vs (Vectorof A)]) (Mutable-Array A)]{
Returns a mutable array with @tech{shape} @racket[ds] and elements @racket[vs]; assumes
@racket[vs] are in row-major order. If there are too many or too few elements in @racket[vs],
@racket[(make-mutable-array ds vs)] raises an error.
@examples[#:eval typed-eval
(make-mutable-array #(3 3) #(0 1 2 3 4 5 6 7 8))
(make-mutable-array #() #(singleton))
(make-mutable-array #(4) #(1 2 3 4 5))]
}
@defproc[(array->mutable-array [arr (Array A)]) (Mutable-Array A)]{ @defproc[(array->mutable-array [arr (Array A)]) (Mutable-Array A)]{
Returns a mutable array with the same elements as @racket[arr]. The result is a copy of Returns a mutable array with the same elements as @racket[arr]. The result is a copy of
@racket[arr], even when @racket[arr] is mutable. @racket[arr], even when @racket[arr] is mutable.
@ -664,37 +663,60 @@ This is used as an argument type to @racket[list*->array] and as the return type
Like @racket[(Listof* A)], but for vectors. See @racket[vector*->array] and @racket[array->vector*]. Like @racket[(Listof* A)], but for vectors. See @racket[vector*->array] and @racket[array->vector*].
} }
@deftogether[(@defproc[(list->array [lst (Listof A)]) (Array A)] @deftogether[(@defproc*[([(list->array [lst (Listof A)]) (Array A)]
[(list->array [ds In-Indexes] [lst (Listof A)]) (Array A)])]
@defproc[(array->list [arr (Array A)]) (Listof A)])]{ @defproc[(array->list [arr (Array A)]) (Listof A)])]{
Convert lists to single-axis arrays and back. If @racket[arr] has no axes or more than one axis, Convert lists to @tech{strict}, immutable arrays and back.
it is (conceptually) flattened before being converted to a list.
The two-argument variant of @racket[list->array] assumes the elements in @racket[lst] are in
row-major order.
For @racket[array->list], if @racket[arr] has no axes or more than one axis, it is (conceptually)
flattened before being converted to a list.
@examples[#:eval typed-eval @examples[#:eval typed-eval
(list->array '(1 2 3)) (list->array '(1 2 3))
(list->array '((1 2 3) (4 5))) (list->array '((1 2 3) (4 5)))
(list->array #(2 2) '(1 2 3 4))
(array->list (array #[1 2 3])) (array->list (array #[1 2 3]))
(array->list (array 10)) (array->list (array 10))
(array->list (array #[#[1 2 3] #[4 5 6]]))] (array->list (array #[#[1 2 3] #[4 5 6]]))]
For conversion between nested lists and multidimensional arrays, see @racket[list*->array] and For conversion between nested lists and multidimensional arrays, see @racket[list*->array] and
@racket[array->list*]. @racket[array->list*].
For conversion from flat values to mutable arrays, see @racket[vector->array].
} }
@deftogether[(@defproc[(vector->array [vec (Vectorof A)]) (Array A)] @deftogether[(@defproc*[([(vector->array [vec (Vectorof A)]) (Mutable-Array A)]
[(vector->array [ds In-Indexes] [vec (Vectorof A)]) (Mutable-Array A)])]
@defproc[(array->vector [arr (Array A)]) (Vectorof A)])]{ @defproc[(array->vector [arr (Array A)]) (Vectorof A)])]{
Like @racket[list->array] and @racket[array->list], but for vectors. Like @racket[list->array] and @racket[array->list], but for vectors.
@examples[#:eval typed-eval
(vector->array #(1 2 3))
(vector->array #((1 2 3) (4 5)))
(vector->array #(2 2) #(1 2 3 4))
(array->vector (array #[1 2 3]))
(array->vector (array 10))
(array->vector (array #[#[1 2 3] #[4 5 6]]))]
For conversion between nested vectors and multidimensional arrays, see @racket[vector*->array] and
@racket[array->vector*].
} }
@defproc[(list*->array [lsts (Listof* A)] [pred? ((Listof* A) -> Any : A)]) (Array A)]{ @defproc[(list*->array [lsts (Listof* A)] [pred? ((Listof* A) -> Any : A)]) (Array A)]{
Converts a nested list of elements of type @racket[A] to an array. The predicate @racket[pred?] Converts a nested list of elements of type @racket[A] to a @tech{strict} array.
identifies elements of type @racket[A]. The shape of @racket[lsts] must be rectangular. The predicate @racket[pred?] identifies elements of type @racket[A].
The shape of @racket[lsts] must be rectangular.
@examples[#:eval typed-eval @examples[#:eval typed-eval
(list*->array 'singleton symbol?) (list*->array 'singleton symbol?)
(list*->array '(0 1 2 3) byte?) (list*->array '(0 1 2 3) byte?)
(list*->array (list (list (list 5) (list 2 3)) (list*->array (list (list (list 5) (list 2 3))
(list (list 4.0) (list 1.4 0.2 9.3))) (list (list 4.0) (list 1.4 0.2 9.3)))
(make-predicate (Listof Nonnegative-Real)))] (make-predicate (Listof Nonnegative-Real)))]
The last example demonstrates why a predicate is required. There is no well-typed Typed Racket
function that behaves like @racket[list*->array] but does not require @racket[pred?], because There is no well-typed Typed Racket function that behaves like @racket[list*->array] but does not
without it, there is no way to distinguish between rows and elements. require @racket[pred?].
Without an element predicate, there is no way to prove to the type checker that
@racket[list*->array]'s implementation correctly distinguishes elements from rows.
} }
@defproc[(array->list* [arr (Array A)]) (Listof* A)]{ @defproc[(array->list* [arr (Array A)]) (Listof* A)]{
@ -715,9 +737,10 @@ Like @racket[array->list*], but produces nested vectors of elements.
} }
@defproc[(array-list->array [arrs (Listof (Array A))] [axis Integer 0]) (Array A)]{ @defproc[(array-list->array [arrs (Listof (Array A))] [axis Integer 0]) (Array A)]{
Concatenates @racket[arrs] along axis @racket[axis] to form a new array. If the arrays have Concatenates @racket[arrs] along axis @racket[axis] to form a new array.
different shapes, they are broadcast first. The axis number @racket[axis] must be nonnegative If the arrays have different shapes, they are broadcast first.
and @italic{no greater than} the number of axes after broadcasting. The axis number @racket[axis] must be nonnegative and @italic{no greater than} the number of axes in
the highest dimensional array in @racket[arrs].
@examples[#:eval typed-eval @examples[#:eval typed-eval
(array-list->array (list (array 0) (array 1) (array 2) (array 3))) (array-list->array (list (array 0) (array 1) (array 2) (array 3)))
(array-list->array (list (array 0) (array 1) (array 2) (array 3)) 1) (array-list->array (list (array 0) (array 1) (array 2) (array 3)) 1)
@ -1756,7 +1779,7 @@ in-unsafe-array-indexes
make-unsafe-array-set-proc make-unsafe-array-set-proc
make-unsafe-array-proc make-unsafe-array-proc
unsafe-build-array unsafe-build-array
unsafe-mutable-array unsafe-vector->array
unsafe-flarray unsafe-flarray
unsafe-array-transform unsafe-array-transform
unsafe-array-axis-reduce unsafe-array-axis-reduce

View File

@ -48,7 +48,7 @@
(check-equal? (make-indexes-vector 2 3) (check-equal? (make-indexes-vector 2 3)
#(#(0 0) #(0 1) #(0 2) #(1 0) #(1 1) #(1 2) #(2 0) #(2 1) #(2 2))) #(#(0 0) #(0 1) #(0 2) #(1 0) #(1 1) #(1 2) #(2 0) #(2 1) #(2 2)))
(let ([arr (make-mutable-array #(4) #(a b c d))]) (let ([arr (vector->array #(4) #(a b c d))])
(check-eq? arr (array-strict arr))) (check-eq? arr (array-strict arr)))
(let ([arr (build-array #() (λ (js) 'foo))]) (let ([arr (build-array #() (λ (js) 'foo))])
@ -87,34 +87,34 @@
;; list*->array ;; list*->array
(check-equal? (list*->array 1.0 flonum?) (check-equal? (list*->array 1.0 flonum?)
(make-mutable-array #() #(1.0))) (vector->array #() #(1.0)))
(check-equal? (list*->array '[] flonum?) (check-equal? (list*->array '[] flonum?)
(make-mutable-array #(0) #())) (vector->array #(0) #()))
(check-equal? (list*->array '[[]] flonum?) (check-equal? (list*->array '[[]] flonum?)
(make-mutable-array #(1 0) #())) (vector->array #(1 0) #()))
(check-equal? (list*->array '[1.0] flonum?) (check-equal? (list*->array '[1.0] flonum?)
(make-mutable-array #(1) #(1.0))) (vector->array #(1) #(1.0)))
(check-equal? (list*->array '[[1.0]] flonum?) (check-equal? (list*->array '[[1.0]] flonum?)
(make-mutable-array #(1 1) #(1.0))) (vector->array #(1 1) #(1.0)))
(check-equal? (list*->array '[[[1.0]]] flonum?) (check-equal? (list*->array '[[[1.0]]] flonum?)
(make-mutable-array #(1 1 1) #(1.0))) (vector->array #(1 1 1) #(1.0)))
(check-equal? (list*->array '() listof-flonum?) (check-equal? (list*->array '() listof-flonum?)
(make-mutable-array #() #(()))) (vector->array #() #(())))
(check-equal? (list*->array '[()] listof-flonum?) (check-equal? (list*->array '[()] listof-flonum?)
(make-mutable-array #(1) #(()))) (vector->array #(1) #(())))
(check-equal? (list*->array '[(1.0) (2.0)] listof-flonum?) (check-equal? (list*->array '[(1.0) (2.0)] listof-flonum?)
(make-mutable-array #(2) #((1.0) (2.0)))) (vector->array #(2) #((1.0) (2.0))))
(check-equal? (list*->array '[((1.0)) ((2.0))] listof-flonum?) (check-equal? (list*->array '[((1.0)) ((2.0))] listof-flonum?)
(make-mutable-array #(2 1) #((1.0) (2.0)))) (vector->array #(2 1) #((1.0) (2.0))))
;; --------------------------------------------------------------------------------------------------- ;; ---------------------------------------------------------------------------------------------------
;; array->list* ;; array->list*
@ -156,22 +156,22 @@
;; vector*->array ;; vector*->array
(check-equal? (vector*->array 1.0 flonum?) (check-equal? (vector*->array 1.0 flonum?)
(make-mutable-array #() #(1.0))) (vector->array #() #(1.0)))
(check-equal? ((inst vector*->array Float) #() flonum?) (check-equal? ((inst vector*->array Float) #() flonum?)
(make-mutable-array #(0) #())) (vector->array #(0) #()))
(check-equal? ((inst vector*->array Float) #(#()) flonum?) (check-equal? ((inst vector*->array Float) #(#()) flonum?)
(make-mutable-array #(1 0) #())) (vector->array #(1 0) #()))
(check-equal? ((inst vector*->array Float) #(1.0) flonum?) (check-equal? ((inst vector*->array Float) #(1.0) flonum?)
(make-mutable-array #(1) #(1.0))) (vector->array #(1) #(1.0)))
(check-equal? ((inst vector*->array Float) #(#(1.0)) flonum?) (check-equal? ((inst vector*->array Float) #(#(1.0)) flonum?)
(make-mutable-array #(1 1) #(1.0))) (vector->array #(1 1) #(1.0)))
(check-equal? ((inst vector*->array Float) #(#(#(1.0))) flonum?) (check-equal? ((inst vector*->array Float) #(#(#(1.0))) flonum?)
(make-mutable-array #(1 1 1) #(1.0))) (vector->array #(1 1 1) #(1.0)))
;; --------------------------------------------------------------------------------------------------- ;; ---------------------------------------------------------------------------------------------------
;; array->vector ;; array->vector
@ -303,7 +303,7 @@
(check-equal? (array-map (inst cons Float Float) (check-equal? (array-map (inst cons Float Float)
(array #[1.0 2.0]) (array #[1.0 2.0])
(array #[10.0 20.0])) (array #[10.0 20.0]))
(make-mutable-array #(2) #[(1.0 . 10.0) (2.0 . 20.0)])) (vector->array #(2) #[(1.0 . 10.0) (2.0 . 20.0)]))
;; --------------------------------------------------------------------------------------------------- ;; ---------------------------------------------------------------------------------------------------
;; Fold ;; Fold