Adding dynamic/c and coerce/c
This commit is contained in:
parent
7ebdd3c7f1
commit
d6d9f3ef8c
|
@ -1,6 +1,18 @@
|
||||||
#lang racket
|
#lang racket
|
||||||
|
(require rackunit rackunit/text-ui unstable/contract "helpers.rkt" tests/eli-tester)
|
||||||
|
|
||||||
(require rackunit rackunit/text-ui unstable/contract "helpers.rkt")
|
(test
|
||||||
|
(let ()
|
||||||
|
(define p (make-parameter any/c))
|
||||||
|
(define c (dynamic/c string? p number?))
|
||||||
|
|
||||||
|
(parameterize ([p (coerce/c string->number)])
|
||||||
|
(test
|
||||||
|
(contract c "123" 'pos 'neg) => 123
|
||||||
|
(contract c "123a" 'pos 'neg) =error> "Coercion failed"))
|
||||||
|
|
||||||
|
(test
|
||||||
|
(contract c "123" 'pos 'neg) =error> "broke")))
|
||||||
|
|
||||||
(run-tests
|
(run-tests
|
||||||
(test-suite "contract.ss"
|
(test-suite "contract.ss"
|
||||||
|
|
|
@ -1,6 +1,38 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
(require racket/contract racket/dict racket/match)
|
(require racket/contract racket/dict racket/match)
|
||||||
|
|
||||||
|
(define (dynamic/c pre parameter post)
|
||||||
|
(define pre-ctc (coerce-contract 'pre pre))
|
||||||
|
(define post-ctc (coerce-contract 'post post))
|
||||||
|
(make-contract
|
||||||
|
#:name (build-compound-type-name 'dynamic pre-ctc parameter post-ctc)
|
||||||
|
#:projection
|
||||||
|
(λ (b)
|
||||||
|
(define pre-proj ((contract-projection pre-ctc) b))
|
||||||
|
(define post-proj ((contract-projection post-ctc) b))
|
||||||
|
(λ (x)
|
||||||
|
(define dyn-proj
|
||||||
|
((contract-projection (coerce-contract 'dynamic (parameter))) b))
|
||||||
|
(post-proj
|
||||||
|
(dyn-proj
|
||||||
|
(pre-proj
|
||||||
|
x)))))))
|
||||||
|
|
||||||
|
(define (coerce/c i->o)
|
||||||
|
(make-contract
|
||||||
|
#:name (build-compound-type-name 'coerce i->o)
|
||||||
|
#:projection
|
||||||
|
(λ (b)
|
||||||
|
(λ (x)
|
||||||
|
(or (i->o x)
|
||||||
|
(raise-blame-error b x "Coercion failed"))))))
|
||||||
|
|
||||||
|
(provide/contract
|
||||||
|
[dynamic/c (-> contract? (parameter/c contract?) contract?
|
||||||
|
contract?)]
|
||||||
|
[coerce/c (-> (-> any/c any/c)
|
||||||
|
contract?)])
|
||||||
|
|
||||||
(define path-element?
|
(define path-element?
|
||||||
(or/c path-string? (symbols 'up 'same)))
|
(or/c path-string? (symbols 'up 'same)))
|
||||||
;; Eli: We already have a notion of "path element" which is different
|
;; Eli: We already have a notion of "path element" which is different
|
||||||
|
|
|
@ -222,3 +222,27 @@ immutable dictionaries (which may be passed through a constructor that involves
|
||||||
efficient than the original dictionaries.
|
efficient than the original dictionaries.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@addition[@author+email["Jay McCarthy" "jay@racket-lang.org"]]
|
||||||
|
|
||||||
|
@defproc[(dynamic/c [pre contract?] [dynamic (parameter/c contract?)] [post contract?])
|
||||||
|
contract?]{
|
||||||
|
Returns a contract that applies the @racket[pre] contract, then the contract dynamically bound to the @racket[dynamic] parameter, then the @racket[post] contract.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(coerce/c [coerce (-> any/c any/c)])
|
||||||
|
contract?]{
|
||||||
|
Returns a contract that applies @racket[coerce] to all values and blames the positive party if @racket[coerce] returns false. This is a light-weight way to create a contract from a simple projection.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defexamples[
|
||||||
|
#:eval (eval/require 'racket/contract 'unstable/contract)
|
||||||
|
|
||||||
|
(define p (make-parameter any/c))
|
||||||
|
(define c (dynamic/c string? p number?))
|
||||||
|
|
||||||
|
(contract c "123" 'pos 'neg)
|
||||||
|
|
||||||
|
(p (coerce/c string->number))
|
||||||
|
(contract c "123" 'pos 'neg)
|
||||||
|
(contract c "123a" 'pos 'neg)]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user