ericniebler/range-v3 — pull request #74 by morinmorin (2014-11-22 14:51:33+00:00)
Title: Lazy distance comparison for NonSizedIterable

I often need to compare the size of a (possibly large) bidirectional range `rng` with a small number `n`. When the range is large, computing the "full" length (i.e. `distance(rng)`) is inefficient for this purpose; it's enough to compute "partial" length at most `n` or `n + 1`.

I came up with the following solutions to this problem:

### A. "drop at most" range adaptor
Oven's [`dropped(n)`](http://p-stade.sourceforge.net/oven/doc/html/oven/range_adaptors.html#oven.range_adaptors.dropped) range adaptor drops at most `n` elements; it does not penetrate the end of the range even if the range has size less than `n`. (To differentiate it from range-v3's `drop` adaptor, I call it `drop_at_most`.) With this adaptor, we can make comparison without computing the "full" length. For example,
`distance(rng) < n` <--> ` empty(rng | drop_at_most(n - 1))`
`distance(rng) > n` <--> `!empty(rng | drop_at_most(n))`

### B. "bounded distance" function
`bounded_distance(rng, bound)` returns the size of `rng` if the size is less than `bound`, and returns `bound` otherwise. This function increments an iterator at most `bound` times. For example,
`distance(rng) < n` <--> `bounded_distance(rng, n) < n`
`distance(rng) > n` <--> `bounded_distance(rng, n + 1) > n`

### C. "lazy distance" proxy
`lazy_distance(rng)` returns a proxy that can be compared with a number. Actual computation of "partial" length is done when a proxy is compared. For example,
`distance(rng) < n` <--> `lazy_distance(rng) < n`
`distance(rng) > n` <--> `lazy_distance(rng) > n`

However, IMHO, Option A is not so intuitive and Option B is verbose (we need to write `n` twice). I like Option C *very much*, but this approach might be too complex for a simple task and it might be difficult to get into the Standard.

Then I sought another solution and found that the [GHC API](https://downloads.haskell.org/~ghc/latest/docs/html/libraries/ghc/Util.html) has interesting function:
```
listLengthCmp :: [a] -> Int -> Ordering
```
I use this function interface as a fourth solution.

### D. "lazy distance comparison" function
`distance_compare(rng, n)` returns positive (negative) integers if the size of `rng` is larger (smaller) than `n` and returns 0 if the size equals `n`. For example,
`distance(rng) < n` <--> `distance_compare(rng, n) < 0`
`distance(rng) > n` <--> `distance_compare(rng, n) > 0`

Option D is less readable than Option C, but it has good balance between the conciseness of the approach and the readability.

This PR implemented `distance_compare` (Option D) and tests. What do you think?