Version: 4.2.1
6.2 Static Information With Behavior
Synopsis: Improves on Static Information by customizing the behavior of the static name when it is used as an expression or definition form.
Examples: define-struct, define-signature
Related patterns:
This pattern is a variation of the Static Information pattern that lets the names carrying static information to additionally act as ordinary macros. Often the behavior of the “ordinary macro” part is simply to produce a custom syntax error if the name is used in an expression or definition context.
6.2.1 Example
Here’s a variation of the structure definition from the
Static Information example:
(begin-for-syntax |
(define-struct rectype (descriptor-var field-count) |
#:property prop:procedure |
(lambda (self stx) |
(raise-syntax-error #f "improper use of record type" stx)) |
#:omit-define-syntaxes)) |
This version makes instances of rectype act as procedures
via the prop:procedure struct property. The effective arity
of the struct instance is one less than the arity of the procedure
given in the struct definition; invoking a struct instance causes the
procedure to be called with the struct instance added to the front of
the argument list.
The practical consequence is that the procedure above is suitable as a macro transformer. So names bound as record types also act as macros that always raise a syntax error. But their record type information is still accessible via syntax-local-value.
Another behavior we could implement is for a record type name used in
operator position to construct an instance of the record type. Here’s
a definition of the rectype that allows that:
(begin-for-syntax |
(define-struct rectype (descriptor-var field-count) |
#:property prop:procedure |
(lambda (self stx) |
(syntax-case stx () |
[(record-type arg ...) |
#'(make record-type arg ...)] |
[record-type |
(identifier? #'record-type) |
(with-syntax ([(var ...) |
(generate-temporaries |
(for/list ([i (rectype-field-count self)]) |
#'var))]) |
#'(lambda (var ...) (make record-type var ...)))])) |
#:omit-define-syntaxes)) |
We can of course just reuse the make macro from earlier.