I looked through the math/array
documentation, and it wasn't clear to me whether Racket's arrays can have arrays as elements.
This question arose in my mind because if arrays can have arrays as elements, I am a bit confused about how to disambiguate implicit array broadcasting. Perhaps this doesn't arise because math/array
doesn't seem to implicitly convert other Racket objects to arrays before broadcasting, as NumPy does.
There is at least one example in the documentation of an array that contains vectors.
I like that (array 10)
wraps 10
in a zero-dimensional array. It's just the simplest use of the array
syntax, however, so while this is useful in the Racket context, it may not be good to define a procedure array
in another library whose sole use is to wrap objects in zero-dimensional arrays.
A little experimentation gives the answer, sorry:
Welcome to Racket v8.16.0.2 [cs].
> (require math/array)
> (array (vector 0 1 2))
(array '#(0 1 2))
> #(0 1 2)
'#(0 1 2)
> (array-shape (array '#(0 1 2)))
'#()
> (array #(0 1 2))
(array #[0 1 2])
> (array-shape (array #(0 1 2)))
'#(3)
> (array-shape (array (array #[0 1 2])))
'#()
Racket's array
syntax is very nice, while array broadcasting and returning strict
arrays by default makes some simple examples very simple to express ("Make easy things easy and hard things possible."):
heine:~/text/courses> /usr/local/racket/bin/racket
Welcome to Racket v8.16.0.2 [cs].
> (require math/array)
> (array-map * (array #[0 1 2]) (array 2))
(array #[0 2 4])
Using srfi/231
in Gambit is much more verbose, and the result is not printed well by the REPL:
heine:~/text/courses/computation/computational-reals/app> gsi
Gambit v4.9.7-17-g273252c2
> (import srfi/231)
> (array->copy (array-map (lambda (x) (* x 2)) (list*->array 1 '(0 1 2))))
*** ERROR IN (stdin)@2.2-2.13 -- Unbound variable: array->copy
1>
> (array-copy (array-map (lambda (x) (* x 2)) (list*->array 1 '(0 1 2))))
#<%%array #2
domain: #<%%interval #3 dimension: 1 %%volume: 3 lower-bounds: #(0) upper-bounds: #(3)>
getter: #<procedure #4>
unsafe-getter: #<procedure #5>
setter: #<procedure #6>
unsafe-setter: #<procedure #7>
storage-class:
#<storage-class #8
getter: #<procedure #9>
setter: #<procedure #10>
checker: #<procedure #11>
maker: #<procedure #12>
copier: #<procedure #13 vector-copy!>
length: #<procedure #14>
default: #f
data?: #<procedure #15>
data->body: #<procedure #16>>
body: #(0 2 4)
indexer: #<procedure #17>
safe?: #t
in-order?: #t>
I included the mis-typing because the more you have to type, the more likely you are to make a mistake.