If I want to export a struct declaration and a function producing the same struct, do I need to repeat the struct contract twice?
For example, is this necessary? #lang racket
(provide
(contract-out
(struct S ([x number?]))
[f (-> S/c)]))
(struct S (x))
(define S/c (struct/c S number?))
(define (f) (S 123))
could you just use S?
If f
produces incorrect values, that will blame S-x
instead of f
What @samth said. Beware that this does make it possible for functions inside the module to put bad values into the struct fields, so just because the struct is provided with a contract does not mean it’s always impossible to get bad field values. If you want to prevent all instances from having bad field values, rather than just instances created by other modules, you should use the struct-guard/c
contract and the #:guard
option:
(struct S (x) #:guard (struct-guard/c number?))
yes, it all depends on who you’re trusting
@notjack Cool! I did not know struct-guard/c
existed
I don’t struct both parties so :disappointed:
*trust
If your structs contain known types of data (as in, they’re not polymorphic), and they’re used just as plain transparent data carriers rather than like opaque holders of functions, you probably want to use struct-guard/c
unless you have a specific performance reason not to.
Thanks! I’ll go with that and use S?
in the contract for functions
oh, small wrinkle I forgot: struct-guard/c
can’t express contracts like “the number in the min
field must be less than the number in the max
field”
There’s no reason it couldn’t be extended to support that, that just hasn’t been asked for by anyone yet
@rebornwwp has joined the channel