My aim is to populate an array in compile phase (i.e. in a macro), and use it in execution phase. For some reason, though, object returned by a macro is not recognized by Racket as an array. To illustrate the problem, shortest code showing this behaviour:
(require (for-syntax math/array))
(require math/array)
(define-syntax (A stx)
(datum->syntax stx `(define a ,(array #[#[1 2] #[3 4]]))))
(A)
After execution of this macro, 'a' is something, but I don't know what it is. It is not an array ((array? a) -> #f
) nor a string, array-ref is not working on it, obviously, but it prints as: (array #[#[1 2] #[3 4]])
. "class-of" from the "swindle" module claims it is "primitive-class:unknown-primitive", for what it's worth.
I have tried outputting a vector instead of an array, but it works as expected, i.e. resulting value is a vector in execution phase.
I have tried using CommonLisp style defmacro from "compatibility" module, thinking that this may have something to do do with datum->syntax transformation, but this changed nothing.
I have tested this on Win7 with Racket 6.5 and 6.7, as well as on Linux with Racket 6.7 - problem persists.
Any ideas?
update
Thanks to great answers and suggestions, I came up with following solution:
(require (for-syntax math/array))
(require math/array)
(define-syntax (my-array stx)
(syntax-case stx ()
[(_ id)
(let
([arr (build-array
#(20 20)
(lambda (ind)
(let
([x (vector-ref ind 1)]
[y (vector-ref ind 0)])
(list 'some-symbol x y (* x y)))))])
(with-syntax ([syn-arr (eval (read (open-input-string (string-append "#'" (format "~v" arr)))))])
#'(define id syn-arr)))]))
(my-array A)
I'm not sure if this is proper Racket (I welcome all suggestions on code improvement) but here is how it works:
Array is built and stored in "arr" variable. It is then printed to string, prepended with #'
(so that this string represents syntax object now) and evaluated as code. This effectively converts array to syntax object, that can be embedded in macro output.
Advantage of this approach is, that every object that can be written out and then read back by Racket can be output by macro. Disadvantage is, that some objects can't (I'm looking at you, custom struct!) and therefore additional string-creating function may be required in some cases.