Reputation: 1278
In Racket, I want to use a struct's field names for metaprogramming.
For example:
(struct pt [x y])
(struct-fields pt) ;; -> '(x y)
Upvotes: 0
Views: 514
Reputation: 43852
You can’t. You can get the accessors, which here would be pt-x
and pt-y
, but you can’t get just x
and y
alone. Why is this? Well, one reason is that there could actually be duplicates. Consider a scenario involving some pernicious struct subtyping:
#lang racket/base
(struct A [x] #:transparent)
(struct B A [x] #:transparent)
Now a structure of type B
has two x
fields, A-x
and B-x
. For this reason, any macro that tries to use field names alone with structs is broken when subtyping may be involved.
What you can do is use the accessors, instead, which you can achieve by using syntax-local-value
plus extract-struct-info
, then looking at the fourth element of the resulting list. However, honestly, I think that’s too much work, so I wrote a syntax class to do all the hard work for you. Install the syntax-classes
package and use the struct-id
syntax class:
#lang racket/base
(require (for-syntax racket/base
syntax/parse/class/struct-id)
syntax/parse/define)
(define-simple-macro (struct-accessors id:struct-id)
(list id.accessor-id ...))
> (struct pt [x y] #:transparent)
> (struct-accessors pt)
'(#<procedure:pt-x> #<procedure:pt-y>)
Upvotes: 2