On this page:
vectorof/  ic
hash/  ic
string/  ic
bytes/  ic
hash-record/  ic
convert/  ic
9.0.0.1

3 Contracts🔗ℹ

 (require scramble/contract) package: scramble-lib

Added in version 0.4 of package scramble-lib.

procedure

(vectorof/ic elem/c)  impersonator-contract?

  elem/c : contract?

procedure

(hash/ic key/c value/c)  impersonator-contract?

  key/c : contract?
  value/c : contract?

value

string/ic : impersonator-contract?

value

bytes/ic : impersonator-contract?

Like the contracts (vectorof elem/c), (hash/c key/c elem/c), string?, and bytes?, except that the result of the contract’s projection is always immutable and authentic (not a chaperone or impersonator).

Examples:
> (define the-vector (vector))
> (define/contract install!
    (-> (vectorof/ic real?) void?)
    (lambda (v) (set! the-vector v)))
> (define v (vector 1 2 3))
> (install! v)
> (vector-set! v 0 'apple)
> (vector-set! v 1 'banana)
> (eq? the-vector v)

#f

> (vector-ref the-vector 0)

1

If the original value is suitable, the contract projection returns it unchanged.

> (define imm-vec '#(1 2 3))
> (install! imm-vec)
> (eq? the-vector imm-vec)

#t

The value produced by a hash/ic contract uses the same key comparison as the original value.

> (define/contract hash-snapshot
    (-> (hash/ic any/c any/c) any)
    (lambda (h) h))
> (hash-snapshot (make-hasheqv '((1 . "one") (2 . two))))

'#hasheqv((1 . "one") (2 . two))

> (hash-snapshot (hash '(1 2 3) 6 '(4 5) 9))

'#hash(((4 5) . 9) ((1 2 3) . 6))

procedure

(hash-record/ic key=>value/c    
  [#:name name    
  #:other get-other/c    
  #:required required])  impersonator-contract?
  key=>value/c : (hash/c any/c contract?)
  name : any/c = '(hash-record/ic ....)
  get-other/c : (-> any/c contract?) = (lambda (key) any/c)
  required : (or/c 'all list?) = 'all
Produces a contract that accepts hashes, treating them like records and enforcing specific contracts on each of their fields. Specifically, when the contract is applied to a hash, for each key and value in the hash, the contract associated with key by key=>value/c is applied to value. If key=>value/c has no entry for key, then the value contract is obtained from (get-other/c key) instead. The final result of the contract’s projection is immutable and authentic (not a chaperone or impersonator).

If required is 'all, then every key of key=>value/c is required. If required is a list, each element must be a key of key=>value/c, and only those keys are considered required.

> (define point/c (hash-record/ic (hash 'x real? 'y real?)))
> (define/contract point-taxi-dist
    (-> point/c real?)
    (lambda (p) (+ (abs (hash-ref p 'x)) (abs (hash-ref p 'y)))))
> (point-taxi-dist (hash 'x 5 'y 3))

8

> (point-taxi-dist (hash 'x 5 'y 3 'elevation -10))

8

> (point-taxi-dist (hash 'x 5 'y 'north))

point-taxi-dist: contract violation

  expected: real?

  given: 'north

  in: the 'y field of

      the 1st argument of

      (-> (hash-record/ic ....) real?)

  contract from: (definition point-taxi-dist)

  blaming: top-level

   (assuming the contract is correct)

  at: eval:17:0

> (point-taxi-dist (hash 'x 5))

point-taxi-dist: contract violation

  expected: hash with 'y key

  given: '#hash((x . 5))

  in: the 1st argument of

      (-> (hash-record/ic ....) real?)

  contract from: (definition point-taxi-dist)

  blaming: top-level

   (assuming the contract is correct)

  at: eval:17:0

Added in version 0.6 of package scramble-lib.

procedure

(convert/ic convert    
  [#:name name]    
  #:exn->lines exn->lines)  impersonator-contract?
  convert : (-> any/c any/c)
  name : any/c = '(convert/ic ....)
  exn->lines : (lambda (exn) ....)
Produces a contract that applies convert to the given value. If the call to convert produces a value, that is the value produced by the contract. If the call to convert raises an exception, then the contract rejects the given value and the contract error includes a summary of the exception (determined by exn->lines).

The convert procedure should be idempotent; that is, (convert (convert value)) should be equal to (convert value).

The exn->lines function must produce a string suitable for adding to the end of a well-formed error message, such as "" or "\n error: went wrong". The default exn->lines produces "\n error: " followed by the first line of the exception’s message, plus "..." if the message was truncated.

Examples:
> (define (to-string v)
    (cond [(string? v) v]
          [(bytes? v) (bytes->string/utf-8 v)]
          [(symbol? v) (symbol->string v)]
          [else (error 'to-string "cannot convert to string\n  given: ~e" v)]))
> (define stringable/ic
    (convert/ic to-string #:name 'stringable/ic))
> (define/contract concat (-> (listof stringable/ic) string?)
    (lambda (strs) (apply string-append strs)))
> (concat (list "a" #"b" 'c))

"abc"

> (concat (list "a" #"b" 5))

concat: contract violation

  expected: stringable/ic

  given: 5

  error: to-string: cannot convert to string...

  in: an element of

      the 1st argument of

      (-> (listof stringable/ic) string?)

  contract from: (definition concat)

  blaming: top-level

   (assuming the contract is correct)

  at: eval:24:0