In Racket this gives me an error:
(struct point-in-plane (pos_x pos_y))
(struct pixel point-in-plane (color))
(define a-pixel (pixel 1 2 "blue"))
(pixel-color a-pixel)
(pixel-pos_x a-pixel)
(pixel-pos_y a-pixel)
For it to work I need to replace the last two lines with:
(point-in-plane-pos_x a-pixel)
(point-in-plane-pos_y a-pixel)
Similarly in R6RS
#!r6rs
(import (rnrs))
(define-record-type point (fields x y))
(define-record-type cpoint (parent point) (fields color))
(define blue-point (make-cpoint 1 2 "blue"))
(write (cpoint-x blue-point))
Gives a similar error.
What is the reason Scheme (and Racket) don't allow you to access the fields of a subtype that were defined in the parent by: subtypeID-fieldID instead of by parenttypeID-fieldID
I.e. in my case allowing me to use pixel-pos_x and pixel-pos_y .
One reason is that struct
allows you to define sub-structs with identically named fields. For example:
(struct base (x y))
(struct sub base (x y))
(define rec (sub 1 2 3 4))
(base-x rec) ; => 1
(sub-x rec) ; => 3
This is because structs don't really know about field names. From the Racket documentation: "A structure type’s fields are essentially unnamed, though names are supported for error-reporting purposes." You would have to disallow this behavior in order to get extra accessors for sub-structs.
The documentation of the struct form says that it provides accessors and setters for the given fields, but doesn't say that it will automatically re-expose the existing accessors and setters of the parent type with the extra names you're expecting.
When I'm dealing with structs and pulling out the components by name, I often use the racket/match library, especially with the struct* pattern matcher. Usually, I have to deal with multiple components of a struct, and the matcher makes it easy to do so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With