How can I export the struct definition but not the constructor?

What’s the reason you don’t want to use #:constructor-name. It sounds like a perfect solution for this.

But in case you really don’t want to use #:constructor-name, you can use the technique I described in https://racket.discourse.group/t/impersonate-syntax-transformer-cursed-or-not/971. Following results in a run-time error (which seems to be what you want -- but let me know if you want a compile-time error. I can do that too)

#lang racket

(module provider racket
  (require syntax/parse/define
           (for-syntax racket/struct-info))

  (provide get-person
           (rename-out [person* person]))

  (struct person (name))

  (define (get-person db-id)
    (person "foo"))

  (define-syntax-parse-rule (repack x:id constr new-id:id)
    (define-syntax new-id
      (impersonate-procedure
       (syntax-local-value #'x)
       (λ (y)
         (values (syntax-parser [(_ . args) #'(constr . args)]
                                [_:id #'constr])
                 y)))))

  (define better-person
    (procedure-rename
     (λ (name)
       (error "constructor was not provided"))
     'person))

  (repack person better-person person*))

(require 'provider)

(match (get-person 7)  ; this works
  [(person name) name])

; this throws an error
(person 'bob) ; constructor was not provided

1 Like