This is not a problem with copy-struct. It's a weird combination of small bugs.
One of the problems is that the result of (struct-copy Base (Atom 3))) is a Base? struct, not a Atom? struct. More on this later. First, let's analyze a reduced version of your program. Just delete the copy-struct and all the Atom related parts. #lang racket (define (Print stx port mode) (write-string (Pair-cdr stx) port)) (struct Base () #:methods gen:custom-write [(define write-proc Print)]) (struct Pair Base (car cdr)) (Pair-cdr (Base)) ;==> doesn't finish The problem here is that (Pair-cdr (Base)) tries to raise an error, because it's not a Pair. But to be helpful, the error tries to print (Base), but Base has a gen:custom-write procedure that is Print. The problem is that Print calls (Pair-cdr stx) [with stx = (Base)] that raise an error ... So this never finish. The first fix is in the Print procedure, to make it print plain Base struct's (define (Print-Everything stx port mode) (cond [(Atom? stx) (write-string "ATOM " port)] [(Pair? stx) (Print-Everything (Pair-cdr stx) port mode)] ; and Pair-car ? [(Base? stx) (write-string "BASE-OR-UNKNOWN " port)] [else (error "not a BASE :(")])) ; TODO: improve error message (I changed the name. I think that instead of a big cond, it's better to give each derived struct its own gen:custom-write procedure.) The other problem is that struct-copy doesn't really copy all the details of the derived struct. It's more like struct-copy/cast-to. For example, the result of (struct-copy Base (Atom 3))) is a Base? struct, not a Atom? struct. AFAIK it's not possible to clone an arbitrary struct. (It's possible in some cases like #:prefab or #:transparent struct's. http://rosettacode.org/wiki/Polymorphic_copy#Racket) One possible solution is to create a custom gen:custom-copy (require racket/generic) (define-generics custom-copy (struct-copy-x custom-copy)) ;TODO: add wellknown struct's (define (Copy-Everything stx) (cond [(Atom? stx) (Atom (Atom-datum stx))] [(Pair? stx) (Pair (Pair-car stx) (Pair-cdr stx))] [(Base? stx) (Base)] [else (error "not a BASE :(")])) ; TODO: improve error message (Also, instead of a big cond, it's better to give each derived struct its own gen:custom-copy.) And now the example is (struct Base () #:methods gen:custom-write [(define write-proc Print-Everything)] #:methods gen:custom-copy [(define struct-copy-x Copy-Everything)]) (struct Atom Base (datum)) (struct Pair Base (car cdr)) (define t (struct-copy-x (Atom 3))) t ;--- Gustavo On Sat, Mar 1, 2014 at 7:50 AM, Jon Stenerson <jonstener...@comcast.net> wrote: > When I put the following in the DrRacket definitions window and then > evaluate t, it works for a few seconds and runs out of memory. Anyone > understand the problem? > > #lang racket > > (define (Print stx port mode) > (if (Atom? stx) > (write-string "ATOM " port) > (Print (Pair-cdr stx) port mode))) > > (struct Base () > #:methods gen:custom-write > [(define write-proc Print)]) > > (struct Atom Base (datum)) > (struct Pair Base (car cdr)) > > (define t (struct-copy Base (Atom 3))) > ____________________ > Racket Users list: > http://lists.racket-lang.org/users ____________________ Racket Users list: http://lists.racket-lang.org/users