On this page:
comparator?
compare
1.10.1 Constructing Comparators
comparator-map
make-comparator
comparator-reverse
1.10.2 Predefined Comparators
real<=>
comparable-real?
string<=>
1.10.3 Comparison Constants
comparison?
lesser
greater
equivalent
1.10.4 Comparator Contracts
comparator/  c
1.10.5 Comparator Chaperones and Impersonators
comparator-impersonate
7.6

1.10 Comparators

 (require rebellion/base/comparator) package: rebellion

A comparator is an object that compares two values and determines whether one is greater than the other, or whether they are equivalent. This comparison must respect some total ordering, meaning that for any two values x and y:

Note that the third requirement above does not imply that all equivalent values must be equal?. For example, the real<=> comparator considers 3 and 3.0 equivalent, but (equal? 3 3.0) returns false. A comparator for which all equivalent values are also equal is said to be consistent with equality, and comparators which do not satisfy this stronger property are inconsistent with equality. All comparators defined in rebellion/base/comparator are consistent with equality unless otherwise stated.

procedure

(comparator? v)  boolean?

  v : any/c
A predicate for comparators.

procedure

(compare comparator left right)  comparison?

  comparator : comparator?
  left : any/c
  right : any/c
Returns whether left is less than, greater than, or equivalent to right.

Examples:
> (compare real<=> 5 8)

#<lesser>

> (compare string<=> "foo" "bar")

#<greater>

1.10.1 Constructing Comparators

procedure

(comparator-map comparator f [#:name name])  comparator?

  comparator : comparator?
  f : (-> any/c any/c)
  name : (or/c interned-symbol? #f) = #f
Wraps comparator as a comparator that first calls f on both of its inputs before comparing them. Beware that this often creates a comparator that is inconsistent with equality.

Examples:
> (define-record-type circle (color radius))
> (define circle<=> (comparator-map real<=> circle-radius))
> (compare circle<=>
           (circle #:color 'green #:radius 5)
           (circle #:color 'blue #:radius 8))

#<lesser>

procedure

(make-comparator function [#:name name])  comparator?

  function : (-> any/c any/c comparison?)
  name : (or/c interned-symbol? #f) = #f
Constructs a comparator named name that compares values by calling function. Most users should use comparator-map to wrap an existing comparator instead of constructing one directly.

Examples:
(define symbol<=>
  (make-comparator
   (λ (left right)
     (cond [(symbol<? left right) lesser]
           [(equal? left right) equivalent]
           [else greater]))
   #:name 'symbol<=>))

 

> (compare symbol<=> 'apple 'banana)

#<lesser>

> (compare symbol<=> 'apple 'aardvark)

#<greater>

procedure

(comparator-reverse comparator)  comparator?

  comparator : comparator?
Reverses comparator, returning a comparator that considers one value greater than another when comparator would consider it lesser and vice-versa.

Examples:
> (compare real<=> 2 5)

#<lesser>

> (compare (comparator-reverse real<=>) 2 5)

#<greater>

1.10.2 Predefined Comparators

A comparator that compares real numbers. Note that not all values that satisfy the real? predicate can be compared: the not-a-number constants +nan.0 and +nan.0 are disallowed.

Examples:
> (compare real<=> 42 99.99)

#<lesser>

> (compare real<=> 42 +inf.0)

#<lesser>

> (compare real<=> 42 -inf.0)

#<greater>

> (compare real<=> 42 +nan.0)

real<=>: contract violation

  expected: comparable-real?

  given: +nan.0

  in: an operand of

      (comparator/c comparable-real?)

  contract from:

      <pkgs>/rebellion/private/comparator.rkt

  blaming: top-level

   (assuming the contract is correct)

  at: <pkgs>/rebellion/private/comparator.rkt:23.3

Beware that this comparator is inconsistent with equality, as it ignores the exactness of the compared numbers. This is the same behavior as <, =, and >, but it means that two un-equal? numbers may compare equivalent.

Examples:
> (compare real<=> 5 5.0)

#<equivalent>

> (compare real<=> -0.0 0.0)

#<equivalent>

> (compare real<=> +inf.0 +inf.0)

#<equivalent>

procedure

(comparable-real? v)  boolean?

  v : any/c
A predicate that identifies real numbers that can be compared sensibly. This predicate is almost identical to real?, with the exception that it rejects the not-a-number constants.

Examples:
> (comparable-real? 42)

#t

> (comparable-real? +inf.0)

#t

> (comparable-real? +nan.0)

#f

A comparator that lexicographically compares immutable strings. Mutable strings are disallowed, to prevent clients from concurrently mutating a string while it’s being compared.

Examples:
> (compare string<=> "aardvark" "zebra")

#<lesser>

> (compare string<=> "aardvark" (make-string 5 #\z))

string<=>: contract violation

  expected: immutable-string?

  given: "zzzzz"

  in: an operand of

      (comparator/c immutable-string?)

  contract from:

      <pkgs>/rebellion/private/comparator.rkt

  blaming: top-level

   (assuming the contract is correct)

  at: <pkgs>/rebellion/private/comparator.rkt:24.3

1.10.3 Comparison Constants

procedure

(comparison? v)  boolean?

  v : any/c
A predicate for comparison constants.

A comparison constant indicating that the left value of a comparison is smaller than the right value.

A comparison constant indicating that the left value of a comparison is greater than the right value.

A comparison constant indicating that the left value of a comparison is equivalent to the right value. Note that equivalent values may not be equal?, depending on the comparator used.

1.10.4 Comparator Contracts

procedure

(comparator/c operand-contract)  contract?

  operand-contract : contract?
A contract combinator for comparators. Returns a contract that enforces that the contracted value is a comparator, and wraps the comparator to check every value it compares with operand-contract. If operand-contract is a chaperone contract, then the returned contract is as well.

Examples:
(define/contract even-integer<=>
  (comparator/c (and/c integer? even?))
  real<=>)

 

> (compare even-integer<=> 2 8)

#<lesser>

> (compare even-integer<=> 3 8)

even-integer<=>: contract violation

  expected: even?

  given: 3

  in: an and/c case of

      an operand of

      (comparator/c (and/c integer? even?))

  contract from: (definition even-integer<=>)

  blaming: top-level

   (assuming the contract is correct)

  at: eval:2.0

1.10.5 Comparator Chaperones and Impersonators

procedure

(comparator-impersonate comparator 
  [#:operand-guard operand-guard 
  #:properties properties 
  #:comparison-marks marks 
  #:chaperone? chaperone?]) 
  comparator?
  comparator : comparator?
  operand-guard : (or/c (-> any/c any/c #f)) = #f
  properties : (hash/c impersonator-property? any/c #:immutable #t)
   = empty-hash
  marks : immutable-hash? = empty-hash
  chaperone? : boolean? = (false? operand-guard)
Returns an impersonator of comparator. Whenever the impersonator comparator is used to compare two values, if operand-guard is not false, it is applied once to each value. The application of the comparator’s comparison function to those two values is wrapped in the continuation marks given by marks. Additionally, the returned impersonator includes an impersonator property for each property and value entry within properties. The returned impersonator is equal? to comparator.

If chaperone? is true, the returned impersonator is a chaperone. In that case, operand-guard must always return a value equal to the one it is given. Furthermore, any impersonators returned from operand-guard must be chaperones.

Examples:
(define printing-real<=>
  (comparator-impersonate real<=>
                          #:operand-guard (λ (x) (printf "Got ~a\n" x) x)
                          #:chaperone? #t))

 

> (compare printing-real<=> 4 8)

Got 4

Got 8

#<lesser>

> (chaperone-of? printing-real<=> real<=>)

#t