@tiotolstoy has joined the channel
@kellysmith12.21 I think a good use of define/contract
is generic private utilities used by a module, since they’re unrelated to the module’s purpose and it’s not worth putting them in a separate file if they’re simple one-offs. But honestly the only thing I use define/contract
for is debugging in the early stages of development of a module.
@badkins it’s more about organization. Putting contracts and provide specs at the top of a module makes it easy to tell at a glance what the public API of the module is. This is really useful in codebases larger than a dozen or so modules. See also the style guide’s comments on module organization https://docs.racket-lang.org/style/Units_of_Code.html\|https://docs.racket-lang.org/style/Units_of_Code.html
also, it’s much easier to verify that all the callers of some function are correct if you can see all the callsites in one file (and that file is reasonably sized). And sometimes a module has a valid reason to privately violate its own invariants while presenting a stricter interface to external code
@notjack I’ll have to give that some thought. It’s been handy to have the contract at the function definition for me. It’s been a while, but I think that’s how I organized my Haskell functions also.
@badkins feel free to look here for examples https://github.com/jackfirth/rebellion/tree/master/private\|https://github.com/jackfirth/rebellion/tree/master/private
I definitely see a benefit in having the contracts at the top in the provide
, but I also like seeing the contract for a function at the definition. A comment might suffice in some cases for mature code.
Yeah, I really want contracts next to the functions. I only switched from define/contract
to contract-out
so that it would stop blaming the function definition site when I passed the wrong arguments to a function.
I also like keeping the contract next to the function definition. I supposed it’d be straightforward to make a define/contract-out
form that provides the function. That would move the provide away from the traditional location at the top of the module, but having the signature with the definition helps keep things clear for me.
I still like keeping a list of my exported names in one place, so I’ve been meaning to write myself some kind of declaration form that would define both a function and a provide transformer for it at the same time, with the latter expanding into contract-out
.
I like that idea.
It’s not that I don’t want to specify the contracts of what I export from a module, but I wanna put contracts on things I don’t export too, especially in case I want to switch on contract-checking for them if I’m tracking down a bug. I kind of want to think of every export as a recontract-out
of selected parts of an internal API.
That would make debugging simpler.
Is there a provide
form like struct-out
, but that can attach contracts to the functions? It appears that they have to be manually provided.
Perhaps it’s preferable to use struct/contract
then provide with struct-out
?