Check contracts
jackfirth opened this issue · comments
Since custom checks aren't functions, they can't be protected by contract-out
without disabling their location-capturing capabilities. A check-out
provide form that allows contracts to be added could work like this:
(provide
(check-out check-foo (check-> foo?)))
(define-check (check-foo foo) ...)
A check that has its contract violated should raise an error rather than causing a check failure. The check->
combinator is used instead of a normal ->
combinator because 1) checks always return void?
, 2) checks have extra "secret" arguments (#:location
and #:expression
specifically) passed in by their macro expansion, and 3) checks don't support user-defined keyword, optional, or rest arguments.
Hmm, check-out
seems like a bad way to fix because it's new & very special purpose syntax.
What about, instead, define-check/contract
?
(Also since check->
is nothing like ->
I think it should be named check/c
... but that's besides the point.)
contract-out
and define/contract
use different parties for blaming: contract-out
uses a boundary between the exporting and importing modules, but define/contract
uses a boundary between the function itself and the rest of the module it's defined in. define-check/contract
would definitely be useful, but it could only work in the way define/contract
does where there's a boundary between the check and it's surrounding module. I think we'd need some sort of provide
form to blame in terms of client modules.
Also, +1 to check/c
.
Good point about the boundaries.
Well I think the best fix would be changing contract-out
to handle macros.
I'm not sure how to do that, so +1 to check-out
.