Struct subtype with default/fixed value of super-type

49 views
Skip to first unread message

Marc Kaufmann

unread,
Mar 15, 2019, 6:55:22 AM3/15/19
to Racket Users
Hi all,

suppose I have a struct `(struct fish (size name) #:transparent)` and a sub-type `(struct shark fish (scares-people?) #:transparent)`. What if I want all sharks to have size 'large by default whenever I create one, so that I create them via:

(define white-shark (shark "The big white" #t))

rather than

(define white-shark (shark 'big "The big white" #t))

Is that possible to do, other than defining my own wrapper? If it is not possible with the current structures, I guess it would be bad practice to overwrite the `shark` constructor, and rather create a `my-shark` constructor to avoid (hypothetical) reader of my code wouldn't get confused.

Best,
Marc

Luis Sanjuán

unread,
Mar 16, 2019, 3:24:37 AM3/16/19
to Racket Users
Maybe #:auto/#:auto-value is what you want:

```
(struct fish (name [size #:auto])
#:auto-value 'big
#:transparent)


(struct shark fish (scares-people?) #:transparent)

(define white-shark (shark "The big white" #t))
```

Marc Kaufmann

unread,
Mar 18, 2019, 9:11:46 AM3/18/19
to Luis Sanjuán, Racket Users
Yes, I saw that, the problem is that I want to be able to set a (potentially different) default value for the sub-type shark than for the sub-type guppy. So if I set the value to 'big for all `fish`, then I can't do that. Essentially, I'd need an #:auto for every sub-type, but the #:auto refers to a parent/super field.

I'll just run with defining a custom constructor.

--
You received this message because you are subscribed to a topic in the Google Groups "Racket Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/racket-users/TthsE0FZDB0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to racket-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jérôme Martin

unread,
Mar 18, 2019, 9:46:50 AM3/18/19
to Racket Users
Once you discover that the default constructor for a struct is just a simple procedure that was generated for you, it's not that big of deal to just make your own and export it like this:

(provide
  (except-out (struct-out fish) fish)
  (rename-out (make-fish fish)))

All the code relying on it will still work.
Except I guess if you pass through different phase levels, it becomes a bit more complicated because you have a syntax attached at compile-time to the identifier. But that's another issue.
Correct me if I'm wrong.

Marc Kaufmann

unread,
Mar 18, 2019, 10:08:05 AM3/18/19
to Jérôme Martin, Racket Users
While I did know that I could define my own, I was going to do it while providing-out another function make-fish and make-shark, but it's nice to know that this allows me to locally define make-fish, while it looks to the outside like (fish ...).

Thanks to including sufficient numbers of mundane bugs in my code (all well-maintained in version control, for quick deployment on docker), I rarely get to worry about phases - it just isn't where the highest gains are. :-)

--

Jérôme Martin

unread,
Mar 20, 2019, 10:32:00 AM3/20/19
to Marc Kaufmann, Racket Users
To go further, if you wonder how to make this work for `match` and inheriting, see this stackoverflow question: https://stackoverflow.com/questions/55262818/how-to-override-a-struct-constructor-while-still-providing-the-struct-metadata-f
Reply all
Reply to author
Forward
0 new messages