On this page:
6.2.1 Example
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.