Adding dynamic/c and coerce/c

This commit is contained in:
Jay McCarthy 2010-12-04 22:11:23 -07:00
parent 7ebdd3c7f1
commit d6d9f3ef8c
3 changed files with 69 additions and 1 deletions

View File

@ -1,6 +1,18 @@
#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
(test-suite "contract.ss"

View File

@ -1,6 +1,38 @@
#lang racket/base
(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?
(or/c path-string? (symbols 'up 'same)))
;; Eli: We already have a notion of "path element" which is different

View File

@ -222,3 +222,27 @@ immutable dictionaries (which may be passed through a constructor that involves
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)]