By default, the Racket struct macro creates two bindings for the name: a runtime binding, and a transformer binding. You can shift these around with #:name
and #:constructor-name
, but as far as I know, you can't supply the runtime name binding while keeping the transformer binding.
Here are some examples using a macro that simulates the ability to do this "correctly" (in my opinion of course):
racket> (struct* these (fields) #:name-expr (lambda args (these-constructor args)))
racket> (these 1 2 3)
(these '(1 2 3))
racket> (struct* singleton (a b) #:name-expr (singleton-constructor 'hello 'world))
racket> singleton
(singleton 'hello 'world)
To keep the examples clear and concise, the macro also defines #:constructor
and #:transparent
. Unfortunately, the macro also uses #:name
which of course, breaks the interface to struct-out
and pattern matching. If this could be achieved without using #:name
, then I feel like it would solve the very common problem of the constructor being the wrong value for the struct's runtime name binding. The two issues to solve are:
- the name must still be exported by struct-out as a runtime binding.
- the name must still encapsulate information about the structure type as a transformer binding.
I actually feel like I run into this issue every time I define a set of structures in Racket.
--
Anthony Carrico