The arrays from the math library performs best when using operations that work on an entire axis (think row or column) at a time. Using `array-ref`

and `array-set!`

in a loop will be slower than using `array-ref`

and `array-set!`

from Typed Racket due to contract checking of the array.

But we can reduce the number of times the contract is checked.

```
(: array-getter (All (A) ((Array A) -> (Indexes -> A))))
(define (array-getter arr)
(λ (js)
(array-ref arr js)))
```

The idea is to use let `array-getter`

getter check that the input is an array,

and return a function that only needs to check the type of the indexes.

It is used like this:

```
(define M (mutable-array #[#[0 1] #[2 3]]))
(define M_ (array-getter M))
(M_ #(0 0))
```

As an extra speed boost `unsafe-array-ref`

can be used instead.

The same approach works for `array-set!`

.

```
#lang typed/racket/base
(require math/array)
(provide array-getter array-setter unsafe-array-getter unsafe-array-setter)
(: array-getter (All (A) ((Array A) -> (Indexes -> A))))
(define (array-getter arr)
(λ (js) (array-ref arr js)))
(: array-setter (All (A) ((Settable-Array A) -> (Indexes A -> Void))))
(define (array-setter arr)
(λ (js value) (array-set! arr js value)))
(: unsafe-array-getter (All (A) ((Array A) -> (Indexes -> A))))
(define (unsafe-array-getter arr)
(λ (js) (unsafe-array-ref arr js)))
(: unsafe-array-setter (All (A) ((Settable-Array A) -> (Indexes A -> Void))))
(define (unsafe-array-setter arr)
(λ (js value) (unsafe-array-set! arr js value)))
```

A small benchmark reveals that the speed up from untyped Racket is well worth using `array-getter`

or `unsafe-array-getter`

.

```
array-ref cpu time: 4508 real time: 4531 gc time: 234
unsafe-array-ref cpu time: 3856 real time: 3874 gc time: 186
array-getter cpu time: 2091 real time: 2101 gc time: 85
unsafe-array-ref cpu time: 1355 real time: 1362 gc time: 55
```

The benchmark for the setter version:

```
array-set! cpu time: 5978 real time: 6007 gc time: 244
unsafe-array-set! cpu time: 5316 real time: 5341 gc time: 223
array-setter! cpu time: 2296 real time: 2305 gc time: 90
unsafe-array-setter cpu time: 1563 real time: 1570 gc time: 61
```

The whole benchmark:

```
#lang racket/base
(require math/array
"array-experiment.rkt")
(define M (mutable-array #[#[0 1] #[2 3]]))
(define M_ (array-getter M))
(define M! (array-setter M))
(define %M_ (unsafe-array-getter M))
(define %M! (unsafe-array-setter M))
(M_ #(0 0))
(M! #(0 0) 42)
(M_ #(0 0))
(define js (vector 0 0))
(time (for ([n (in-range 100000)])
(array-ref M js)))
(time (for ([n (in-range 100000)])
(unsafe-array-ref M js)))
(time (for ([n (in-range 100000)])
(M_ js)))
(time (for ([n (in-range 100000)])
(%M_ js)))
;; cpu time: 4508 real time: 4531 gc time: 234
;; cpu time: 3856 real time: 3874 gc time: 186
;; cpu time: 2091 real time: 2101 gc time: 85
;; cpu time: 1355 real time: 1362 gc time: 55
(time (for ([n (in-range 100000)])
(array-set! M js 42)))
(time (for ([n (in-range 100000)])
(unsafe-array-set! M js 42)))
(time (for ([n (in-range 100000)])
(M! js 42)))
(time (for ([n (in-range 100000)])
(%M! js 42)))
;; cpu time: 5978 real time: 6007 gc time: 244
;; cpu time: 5316 real time: 5341 gc time: 223
;; cpu time: 2296 real time: 2305 gc time: 90
;; cpu time: 1563 real time: 1570 gc time: 61
```