There are several ways to do that. The most obvious one is to use:
(define-struct thing (a b c) #:transparent)
which makes the struct accessible for the kind of low-level inspection that the printout does. Another alternative is to use your own printer:
(define-struct thing (a b c)
#:property prop:custom-write
(lambda (thing port write?)
(fprintf port (if write? "{~s,~s,~s}" "{~a,~a,~a}")
(thing-a thing) (thing-b thing) (thing-c thing))))
But note that the "constructor" output style tries to write some things differently. Also note that you could combine both of these to make it have its own writer as well as being transparent. (Making it transparent is basically making it possible for any code to access the fields in a thing
instance, for example, equal?
can dig into it.)
Finally, for some uses a more fitting facility is to use "prefab" structs:
(define-struct thing (a b c) #:prefab)
What usually happens is that each define-struct
generates a new type, even if one was already defined. But with a prefab struct it's as if there is one type that pre-exists and you're just binding some functions (the constructor, predicate, and accessors) to work with this preexisting type.