Reputation: 2137
Consider the following racket code to get a list of accessor
s of a given struct:
#lang racket
(require (for-syntax syntax/parse racket/struct-info racket/list))
(struct point [x y])
;; get the list of accessors from a struct
;; ex. (get point) = '(point-x point-y)
(define-syntax (get stx)
(syntax-parse stx
[(_ struct)
(define struct-info (extract-struct-info (syntax-local-value #'struct)))
(define accessors-list (map syntax-e (fourth struct-info)))
#``(#,@accessors-list)]))
(get point)
Using syntax-local-value
, we can extract the value of the identifier bound by the pattern variable struct
.
Using extract-struct-info
, we can extract the structure type information in a list form (it has 6 elements). From here the accessors list can be extracted (it's the fourth element in the list).
Question
How can I access the information about a struct (as shown in Structure Type Transformer Binding) at the non-macro level? The two functions above cannot be used directly on structs outside a transformer because the struct is a procedure at that point (and extract-struct-info
takes in a struct-info
).
Upvotes: 3
Views: 254
Reputation: 10653
You cannot use syntax-local-value
and extract-struct-info
at run time. You must use run-time struct introspection instead.
If you make your struct transparent, like this:
(struct point [x y] #:transparent)
then you can get analogous values from a point instance using struct-info
and struct-type-info
:
(define a-point (point 3 4))
(define-values (type skipped?) (struct-info a-point))
;; type = #<struct-type:point>, skipped = #f
(define-values (name inits autos acc mut imms super super-skipped?)
(struct-type-info type))
(acc a-point 0) ;; => 3
The value of type
above is the same as struct:point
(implicitly defined by the struct definition), so if you know you're dealing with a point struct specifically, you coud use that instead. You still need #:transparent
(or you need a sufficiently powerful inspector) to use struct-type-info
, though.
Upvotes: 4