Atharva Shukla
Atharva Shukla

Reputation: 2137

Is it possible to use extract-struct-info outside a macro?

Consider the following racket code to get a list of accessors 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

Answers (1)

Ryan Culpepper
Ryan Culpepper

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

Related Questions