add list*of
This commit is contained in:
parent
608ac636eb
commit
ec4542383c
|
@ -373,14 +373,56 @@ reasons of backwards compatibility.}
|
|||
|
||||
Returns a contract that recognizes a list whose every element matches
|
||||
the contract @racket[c]. Beware that when this contract is applied to
|
||||
a value, the result is not necessarily @racket[eq?] to the input.}
|
||||
a value, the result is not necessarily @racket[eq?] to the input.
|
||||
|
||||
@examples[#:eval (contract-eval)
|
||||
(define/contract some-numbers
|
||||
(listof number?)
|
||||
(list 1 2 3))
|
||||
(define/contract just-one-number
|
||||
(listof number?)
|
||||
11)]
|
||||
|
||||
}
|
||||
|
||||
|
||||
@defproc[(non-empty-listof [c contract?]) list-contract?]{
|
||||
|
||||
Returns a contract that recognizes non-empty lists whose elements match
|
||||
the contract @racket[c]. Beware that when this contract is applied to
|
||||
a value, the result is not necessarily @racket[eq?] to the input.}
|
||||
a value, the result is not necessarily @racket[eq?] to the input.
|
||||
|
||||
@examples[#:eval (contract-eval)
|
||||
(define/contract some-numbers
|
||||
(non-empty-listof number?)
|
||||
(list 1 2 3))
|
||||
|
||||
(define/contract not-enough-numbers
|
||||
(non-empty-listof number?)
|
||||
(list))]
|
||||
}
|
||||
|
||||
@defproc[(list*of [c contract?]) contract?]{
|
||||
|
||||
Returns a contract that recognizes improper lists whose elements match
|
||||
the contract @racket[c]. If an improper list is created with @racket[cons],
|
||||
then its @racket[car] position is expected to match @racket[c] and
|
||||
its @racket[cdr] position is expected to be @racket[(list*of c)]. Otherwise,
|
||||
it is expected to match @racket[c]. Beware that when this contract is applied to
|
||||
a value, the result is not necessarily @racket[eq?] to the input.
|
||||
|
||||
@examples[#:eval (contract-eval)
|
||||
(define/contract improper-numbers
|
||||
(list*of number?)
|
||||
(cons 1 (cons 2 3)))
|
||||
|
||||
(define/contract not-improper-numbers
|
||||
(list*of number?)
|
||||
(list 1 2 3))]
|
||||
|
||||
@history[#:added "6.1.1.1"]
|
||||
}
|
||||
|
||||
|
||||
@defproc[(cons/c [car-c contract?] [cdr-c contract?]) contract?]{
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
(check-not-exn (λ () (test-contract-generation (listof boolean?))))
|
||||
(check-not-exn (λ () (test-contract-generation (listof some-crazy-predicate?))))
|
||||
(check-not-exn (λ () (test-contract-generation (non-empty-listof boolean?))))
|
||||
(check-not-exn (λ () (test-contract-generation (list*of boolean?))))
|
||||
(check-not-exn (λ () (test-contract-generation (list/c boolean? number?))))
|
||||
(check-not-exn (λ () ((car (test-contract-generation (list/c (-> number? number?)))) 0)))
|
||||
|
||||
|
|
|
@ -52,6 +52,11 @@
|
|||
'(list-contract? (listof any/c))
|
||||
#t)
|
||||
|
||||
(test/spec-passed/result
|
||||
'list-contract-10b
|
||||
'(list-contract? (list*of any/c))
|
||||
#f)
|
||||
|
||||
(test/spec-passed/result
|
||||
'list-contract-11
|
||||
'(list-contract? (non-empty-listof any/c))
|
||||
|
|
|
@ -11,4 +11,56 @@
|
|||
(test/no-error '(list/c 'x "x" #t #f #\c #rx"a" #rx#"b"))
|
||||
|
||||
(test/pos-blame 'list1 '(contract (list/c 1 2) (list 1 3) 'pos 'neg))
|
||||
(test/no-error '(contract (list/c 1 2) (list 1 2) 'pos 'neg)))
|
||||
(test/no-error '(contract (list/c 1 2) (list 1 2) 'pos 'neg))
|
||||
|
||||
(test/spec-passed/result
|
||||
'listof1
|
||||
'(contract (listof integer?) '(1 2 3) 'pos 'neg)
|
||||
'(1 2 3))
|
||||
(test/spec-passed/result
|
||||
'listof2
|
||||
'(contract (listof integer?) '() 'pos 'neg)
|
||||
'())
|
||||
(test/pos-blame
|
||||
'listof3
|
||||
'(contract (listof integer?) #f 'pos 'neg))
|
||||
(test/pos-blame
|
||||
'listof4
|
||||
'(contract (listof integer?) (cons 1 2) 'pos 'neg))
|
||||
(test/pos-blame
|
||||
'listof5
|
||||
'(contract (listof integer?) (list #f #t) 'pos 'neg))
|
||||
|
||||
(test/spec-passed/result
|
||||
'nelistof1
|
||||
'(contract (non-empty-listof integer?) '(1 2 3) 'pos 'neg)
|
||||
'(1 2 3))
|
||||
(test/pos-blame
|
||||
'nelistof2
|
||||
'(contract (non-empty-listof integer?) '() 'pos 'neg))
|
||||
(test/pos-blame
|
||||
'nelistof3
|
||||
'(contract (non-empty-listof integer?) #f 'pos 'neg))
|
||||
(test/pos-blame
|
||||
'nelistof4
|
||||
'(contract (non-empty-listof integer?) (cons 1 2) 'pos 'neg))
|
||||
(test/pos-blame
|
||||
'nelistof5
|
||||
'(contract (non-empty-listof integer?) (list #f #t) 'pos 'neg))
|
||||
|
||||
(test/spec-passed/result
|
||||
'imlistof1
|
||||
'(contract (list*of integer?) '(1 2 . 3) 'pos 'neg)
|
||||
'(1 2 . 3))
|
||||
(test/pos-blame
|
||||
'imlistof2
|
||||
'(contract (list*of integer?) '() 'pos 'neg))
|
||||
(test/pos-blame
|
||||
'imlistof3
|
||||
'(contract (list*of integer?) #f 'pos 'neg))
|
||||
(test/pos-blame
|
||||
'imlistof4
|
||||
'(contract (list*of integer?) (list 1 2) 'pos 'neg))
|
||||
(test/pos-blame
|
||||
'imlistof5
|
||||
'(contract (list*of integer?) (cons #f #t) 'pos 'neg)))
|
|
@ -217,17 +217,15 @@
|
|||
|
||||
(test-name '(listof boolean?) (listof boolean?))
|
||||
(test-name '(listof any/c) (listof any/c))
|
||||
(test-name '(listof boolean?) (listof boolean?))
|
||||
(test-name '(listof any/c) (listof any/c))
|
||||
(test-name '(listof boolean?) (listof boolean?))
|
||||
(test-name '(listof (-> boolean? boolean?)) (listof (-> boolean? boolean?)))
|
||||
|
||||
(test-name '(non-empty-listof boolean?) (non-empty-listof boolean?))
|
||||
(test-name '(non-empty-listof any/c) (non-empty-listof any/c))
|
||||
(test-name '(non-empty-listof boolean?) (non-empty-listof boolean?))
|
||||
(test-name '(non-empty-listof any/c) (non-empty-listof any/c))
|
||||
(test-name '(non-empty-listof boolean?) (non-empty-listof boolean?))
|
||||
(test-name '(non-empty-listof (-> boolean? boolean?)) (non-empty-listof (-> boolean? boolean?)))
|
||||
|
||||
(test-name '(list*of boolean?) (list*of boolean?))
|
||||
(test-name '(list*of any/c) (list*of any/c))
|
||||
(test-name '(list*of (-> boolean? boolean?)) (list*of (-> boolean? boolean?)))
|
||||
|
||||
|
||||
(test-name '(vectorof boolean?) (vectorof boolean?))
|
||||
|
|
|
@ -160,7 +160,9 @@
|
|||
(cons/c (<=/c 1) (cons/c (<=/c 2) (listof (<=/c 3))))
|
||||
(listof (<=/c 4)))
|
||||
(ctest #f contract-stronger? (listof number?) (cons/c number? (cons/c number? (listof any/c))))
|
||||
|
||||
(ctest #t contract-stronger? (list*of (<=/c 2)) (list*of (<=/c 3)))
|
||||
(ctest #f contract-stronger? (list*of (<=/c 3)) (list*of (<=/c 2)))
|
||||
|
||||
(ctest #f contract-stronger? (vectorof (<=/c 3)) (vectorof (<=/c 4)))
|
||||
(ctest #f contract-stronger? (vectorof (<=/c 3)) (vectorof (<=/c 4)))
|
||||
(ctest #t contract-stronger? (vectorof (<=/c 3) #:immutable #t) (vectorof (<=/c 4) #:immutable #t))
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
string-len/c
|
||||
false/c
|
||||
printable/c
|
||||
listof non-empty-listof cons/c list/c
|
||||
listof list*of non-empty-listof cons/c list/c
|
||||
promise/c
|
||||
syntax/c
|
||||
|
||||
|
@ -468,9 +468,14 @@
|
|||
(define eg (generate/choose (listof-ctc-elem-c ctc) fuel))
|
||||
(if eg
|
||||
(λ ()
|
||||
(let loop ([so-far (if (pe-listof-ctc? ctc)
|
||||
'()
|
||||
(list (eg)))])
|
||||
(let loop ([so-far (cond
|
||||
[(pe-listof-ctc? ctc)
|
||||
'()]
|
||||
[(ne-listof-ctc? ctc)
|
||||
(list (eg))]
|
||||
[else
|
||||
;; improper list
|
||||
(eg)])])
|
||||
(rand-choice
|
||||
[1/5 so-far]
|
||||
[else (loop (cons (eg) so-far))])))
|
||||
|
@ -488,17 +493,27 @@
|
|||
(define env (generate-env))
|
||||
(values
|
||||
(λ (lst)
|
||||
(env-stash env elem-ctc (oneof lst)))
|
||||
(env-stash env elem-ctc
|
||||
(oneof
|
||||
(if (im-listof-ctc? ctc)
|
||||
(improper-list->list lst)
|
||||
lst))))
|
||||
(list elem-ctc)))]))
|
||||
|
||||
(define (improper-list->list l)
|
||||
(cond
|
||||
[(pair? l) (cons (car l) (improper-list->list (cdr l)))]
|
||||
[else (list l)]))
|
||||
|
||||
(define (listof-stronger this that)
|
||||
(define this-elem (listof-ctc-elem-c this))
|
||||
(cond
|
||||
[(listof-ctc? that)
|
||||
(define that-elem (listof-ctc-elem-c that))
|
||||
(and (if (pe-listof-ctc? this)
|
||||
(pe-listof-ctc? that)
|
||||
#t)
|
||||
(and (cond
|
||||
[(pe-listof-ctc? this) (pe-listof-ctc? that)]
|
||||
[(im-listof-ctc? this) (im-listof-ctc? that)]
|
||||
[else #t])
|
||||
(contract-stronger? this-elem that-elem))]
|
||||
[(the-cons/c? that)
|
||||
(define hd-ctc (the-cons/c-hd-ctc that))
|
||||
|
@ -520,9 +535,13 @@
|
|||
(define (non-empty-list? x) (and (pair? x) (list? x)))
|
||||
|
||||
(define (list-name ctc)
|
||||
(build-compound-type-name (if (pe-listof-ctc? ctc)
|
||||
'listof
|
||||
'non-empty-listof)
|
||||
(build-compound-type-name (cond
|
||||
[(pe-listof-ctc? ctc)
|
||||
'listof]
|
||||
[(ne-listof-ctc? ctc)
|
||||
'non-empty-listof]
|
||||
[(im-listof-ctc? ctc)
|
||||
'list*of])
|
||||
(listof-ctc-elem-c ctc)))
|
||||
|
||||
(define (list-fo-check ctc)
|
||||
|
@ -538,8 +557,17 @@
|
|||
(and (list? v)
|
||||
(pair? v)
|
||||
(for/and ([e (in-list v)])
|
||||
(elem-fo? e))))]))
|
||||
|
||||
(elem-fo? e))))]
|
||||
[(im-listof-ctc? ctc)
|
||||
(λ (v)
|
||||
(let loop ([v v])
|
||||
(cond
|
||||
[(pair? v)
|
||||
(and (elem-fo? (car v))
|
||||
(loop (cdr v)))]
|
||||
[else
|
||||
(elem-fo? v)])))]))
|
||||
|
||||
(define (listof-projection ctc)
|
||||
(define elem-proj (contract-projection (listof-ctc-elem-c ctc)))
|
||||
(define pred? (if (pe-listof-ctc? ctc)
|
||||
|
@ -549,19 +577,37 @@
|
|||
(define elem-proj+blame (elem-proj (blame-add-listof-context blame)))
|
||||
(cond
|
||||
[(flat-listof-ctc? ctc)
|
||||
(λ (val)
|
||||
(if (pred? val)
|
||||
(begin
|
||||
(for ([x (in-list val)])
|
||||
(elem-proj+blame x))
|
||||
val)
|
||||
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) #f)))]
|
||||
(if (im-listof-ctc? ctc)
|
||||
(λ (val)
|
||||
(let loop ([val val])
|
||||
(cond
|
||||
[(pair? val)
|
||||
(elem-proj+blame (car val))
|
||||
(loop (cdr val))]
|
||||
[else
|
||||
(elem-proj+blame val)]))
|
||||
val)
|
||||
(λ (val)
|
||||
(if (pred? val)
|
||||
(begin
|
||||
(for ([x (in-list val)])
|
||||
(elem-proj+blame x))
|
||||
val)
|
||||
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) #f))))]
|
||||
[else
|
||||
(λ (val)
|
||||
(if (pred? val)
|
||||
(for/list ([x (in-list val)])
|
||||
(elem-proj+blame x))
|
||||
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) #f)))])))
|
||||
(if (im-listof-ctc? ctc)
|
||||
(λ (val)
|
||||
(let loop ([val val])
|
||||
(cond
|
||||
[(pair? val)
|
||||
(cons (elem-proj+blame (car val))
|
||||
(loop (cdr val)))]
|
||||
[else (elem-proj+blame val)])))
|
||||
(λ (val)
|
||||
(if (pred? val)
|
||||
(for/list ([x (in-list val)])
|
||||
(elem-proj+blame x))
|
||||
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) #f))))])))
|
||||
|
||||
(define (listof-val-first-projection ctc)
|
||||
(define elem-proj (get/build-val-first-projection (listof-ctc-elem-c ctc)))
|
||||
|
@ -572,22 +618,43 @@
|
|||
(define elem-proj+blame (elem-proj (blame-add-listof-context blame)))
|
||||
(cond
|
||||
[(flat-listof-ctc? ctc)
|
||||
(λ (val)
|
||||
(if (pred? val)
|
||||
(if (im-listof-ctc? ctc)
|
||||
(λ (val)
|
||||
(λ (neg-party)
|
||||
(for ([x (in-list val)])
|
||||
((elem-proj+blame x) neg-party))
|
||||
val)
|
||||
(λ (neg-party)
|
||||
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) neg-party))))]
|
||||
(let loop ([val val])
|
||||
(cond
|
||||
[(pair? val)
|
||||
((elem-proj+blame (car val)) neg-party)
|
||||
(loop (cdr val))]
|
||||
[else
|
||||
((elem-proj+blame val) neg-party)]))
|
||||
val))
|
||||
(λ (val)
|
||||
(if (pred? val)
|
||||
(λ (neg-party)
|
||||
(for ([x (in-list val)])
|
||||
((elem-proj+blame x) neg-party))
|
||||
val)
|
||||
(λ (neg-party)
|
||||
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) neg-party)))))]
|
||||
[else
|
||||
(λ (val)
|
||||
(if (pred? val)
|
||||
(λ (neg-party)
|
||||
(for/list ([x (in-list val)])
|
||||
((elem-proj+blame x) neg-party)))
|
||||
(λ (neg-party)
|
||||
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) neg-party))))])))
|
||||
(if (im-listof-ctc? ctc)
|
||||
(λ (val)
|
||||
(λ (neg-party)
|
||||
(let loop ([val val])
|
||||
(cond
|
||||
[(pair? val)
|
||||
(cons ((elem-proj+blame (car val)) neg-party)
|
||||
(loop (cdr val)))]
|
||||
[else
|
||||
((elem-proj+blame val) neg-party)]))))
|
||||
(λ (val)
|
||||
(if (pred? val)
|
||||
(λ (neg-party)
|
||||
(for/list ([x (in-list val)])
|
||||
((elem-proj+blame x) neg-party)))
|
||||
(λ (neg-party)
|
||||
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) neg-party)))))])))
|
||||
|
||||
(define flat-prop
|
||||
(build-flat-contract-property
|
||||
|
@ -598,7 +665,7 @@
|
|||
#:generate listof-generate
|
||||
#:exercise listof-exercise
|
||||
#:stronger listof-stronger
|
||||
#:list-contract? (λ (c) #t)))
|
||||
#:list-contract? (λ (c) (not (im-listof-ctc? c)))))
|
||||
(define chap-prop
|
||||
(build-chaperone-contract-property
|
||||
#:name list-name
|
||||
|
@ -608,7 +675,7 @@
|
|||
#:generate listof-generate
|
||||
#:exercise listof-exercise
|
||||
#:stronger listof-stronger
|
||||
#:list-contract? (λ (c) #t)))
|
||||
#:list-contract? (λ (c) (not (im-listof-ctc? c)))))
|
||||
(define full-prop
|
||||
(build-contract-property
|
||||
#:name list-name
|
||||
|
@ -618,7 +685,7 @@
|
|||
#:generate listof-generate
|
||||
#:exercise listof-exercise
|
||||
#:stronger listof-stronger
|
||||
#:list-contract? (λ (c) #t)))
|
||||
#:list-contract? (λ (c) (not (im-listof-ctc? c)))))
|
||||
|
||||
(struct listof-ctc (elem-c))
|
||||
|
||||
|
@ -654,9 +721,26 @@
|
|||
#:property prop:custom-write custom-write-property-proc
|
||||
#:property prop:contract full-prop)
|
||||
|
||||
;; improper lists
|
||||
(struct im-listof-ctc listof-ctc ())
|
||||
|
||||
;; improper, flat
|
||||
(struct imf-listof-ctc im-listof-ctc ()
|
||||
#:property prop:custom-write custom-write-property-proc
|
||||
#:property prop:flat-contract flat-prop)
|
||||
;; improper, chaperone
|
||||
(struct imc-listof-ctc im-listof-ctc ()
|
||||
#:property prop:custom-write custom-write-property-proc
|
||||
#:property prop:chaperone-contract chap-prop)
|
||||
;; improper, impersonator
|
||||
(struct imi-listof-ctc im-listof-ctc ()
|
||||
#:property prop:custom-write custom-write-property-proc
|
||||
#:property prop:contract full-prop)
|
||||
|
||||
(define (flat-listof-ctc? x)
|
||||
(or (pef-listof-ctc? x)
|
||||
(nef-listof-ctc? x)))
|
||||
(nef-listof-ctc? x)
|
||||
(imf-listof-ctc? x)))
|
||||
|
||||
(define (ne->pe-ctc ne-ctc)
|
||||
(define elem-ctc (listof-ctc-elem-c ne-ctc))
|
||||
|
@ -675,11 +759,17 @@
|
|||
[(chaperone-contract? c) (nec-listof-ctc c)]
|
||||
[else (nei-listof-ctc c)]))
|
||||
(define/subexpression-pos-prop (listof raw-c)
|
||||
(define c (coerce-contract 'non-empty-listof raw-c))
|
||||
(define c (coerce-contract 'listof raw-c))
|
||||
(cond
|
||||
[(flat-contract? c) (pef-listof-ctc c)]
|
||||
[(chaperone-contract? c) (pec-listof-ctc c)]
|
||||
[else (pei-listof-ctc c)]))
|
||||
(define/subexpression-pos-prop (list*of raw-c)
|
||||
(define c (coerce-contract 'list*of raw-c))
|
||||
(cond
|
||||
[(flat-contract? c) (imf-listof-ctc c)]
|
||||
[(chaperone-contract? c) (imc-listof-ctc c)]
|
||||
[else (imi-listof-ctc c)]))
|
||||
|
||||
|
||||
(define (blame-add-car-context blame) (blame-add-context blame "the car of"))
|
||||
|
|
Loading…
Reference in New Issue
Block a user