Does it seem weird to anybody else that there's no way to set struct properties without mutual recursion?
Say I'm defining a 2d point struct and want to set the prop:custom-write property to control how points print. I might start with this: (struct point (x y) #:property prop:custom-write (lambda (this out _) (write-string "(point " out) (write (point-x this) out) (write-string " " out) (write (point-y this) out) (write-string ")" out))) This works fine. But if I try to extract that lambda into a named function: (struct point (x y) #:property prop:custom-write write-point) (define (write-point pt out _) ...) That doesn't work, and the error complains that I'm using write-point before it's defined. This error makes sense to me. The property value is associated with the type, not with instances, and the struct form is essentially a macro that expands to a call to `make-struct-type` with a list of property values. So I understand that I need to define those properties before using them in the struct definition: (define (write-point pt out _) ...) (struct point (x y) #:property prop:custom-write write-point) All well and good. But then I decide that defining write-foo for every one of my struct types is tedious, so I define a make-list-type-writer helper function and try to use it: (define ((make-list-type-writer name . accessors) this out _) (write-string "(" out) (write-string name out) (for ([accessor (in-list accessors)]) (write-string " " out) (write (accessor this) out)) (write-string ")" out)) (define write-point (make-list-type-writer "point" point-x point-y)) (struct point (x y) #:property prop:custom-write write-point) And now we've got a problem. This doesn't work because I can't pass the point-x and point-y accessors as arguments to make-list-type-writer. They don't exist yet! So in order to make my property value, I need the struct defined. But in order to define the struct, I need the property value. A workable fix is to delay evaluation somewhere with lambdas: (define write-point (make-list-type-writer "point" (lambda (this) (point-x this)) (lambda (this) (point-y this)))) This feels tedious and unnecessary. Looking at the underlying API of make-struct-type, I can't see any way to avoid this mutual recursion. Which is *weird* to me, because when else are you forced to use mutual recursion? Mutually recursive functions can be transformed into functions that accept the other function as an argument. Mutually recursive modules can (usually) be broken down into smaller modules that don't have any cyclic dependencies. But I can't seem to do the same for structs, which makes it difficult to write nice helper functions for building struct types in a first-class way. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.