We have:
(procedure? (-> any/c any/c)) ; -> #f
(contract? (-> any/c any/c)) ; -> #t
(contract? (λ (x) #t)) ; -> #t
Every procedure satisfying contract (-> any/c any(c) is accepted as a contract, but the reverse is not true. Why not every contract is a procedure too? IIUC, contracts are checked only when crossing a module boundary. May be this is the reason. Would it be possible to make
(-> any/c any/c)
satisfy predicate procedure? too or is the different behaviour within a module and between module crossings a strong argument not to do so?
1 Like
There are several answers.
-
We also have:
(contract? 12) ; -> #t
(contract? '()) ; -> #t
(contract? #f) ; -> #t
Changing procedure?
to recognize the many kinds of primitive values that are automatically promoted/coerced to serve as contracts would be confusing. Usually when we write 12
we are not writing a contract, and it's not clear that the meaning of 12
as a contract is a more natural way to interpret 12
as a procedure than, say, (λ (x) (+ x 12))
or (λ (x) (sequence-ref x 12))
.
-
Many contracts are actually higher-order—including seemingly simple ones, like (-> any/c any/c)
. These contracts cannot give an immediate, definitive answer that some value satisfies the contract: they can say “no, definitely not” or “so far, but we need to keep watching”. Contract attachment forms return chaperones or general impersonators of the original values to detect violations that are not immediately visible.
As a concrete example, consider:
(define/contract (sometimes-too-many-vals x)
(-> any/c any/c)
(if (wednesday?)
(values x x)
x))
-
To give good error messages, especially for higher-order contracts, contract-attachment forms use additional pieces of information, not just the value to be contracted. See the contract
form for some details. Since many of these pieces of information relate to the source location, macros make sense for attaching contracts to values.
-
Many contracts do satisfy procedure?
! Specifically, “flat” (i.e. first-order) contracts can be used directly as procedures, except for automatic promotion. For example, you can write:
((listof natural-number/c) '(1 2 3 4 5)) ; -> #t
To be more general, you can use the predicate flat-contract?
and ensure it is in procedure form using flat-contract-predicate
, or you can use coerce-flat-contract
.
2 Likes
Thanks for the replies. Clarifies much.