"Compares corresponding elements of the given streams using 
 the given [[binary predicate function|comparing]]. Two 
 elements are considered _corresponding_ if they occupy the
 same position in their respective streams. Returns `true` 
 if and only if:
 
 - the two streams have the same number of elements, and 
 - if the predicate is satisfied for every pair of 
   corresponding elements.
 
 Returns `false` otherwise. If both streams are empty, 
 return `true`.
 
 For example:
 
     corresponding({ 1, 2, 3, 4 }, 1:4)
 
 and:
 
     corresponding({ 1, 2, 3, 4 }, \"1234\", 
            (Integer i, Character c) => i.string==c.string)
 
 both evaluate to `true`."
see (`function everyPair`, 
     `function compareCorresponding`)
tagged("Comparisons", "Streams")
since("1.1.0")
shared Boolean corresponding<First,Second>(
    {First*} firstIterable, {Second*} secondIterable,
    "The predicate function that compares an element of the
     [[first stream|firstIterable]] with the corresponding 
     element of the [[second stream|secondIterable]].
     
     By default, the elements are compared by a predicate
     function that returns `true` if and only if the 
     elements are [[equal|Object.equals]] or both `null`."
    Boolean comparing(First first, Second second)
            => if (exists first, exists second) 
                    then first==second
                    else !first exists && 
                         !second exists) {
    value firstIter = firstIterable.iterator();
    value secondIter = secondIterable.iterator();
    while (true) {
        value first = firstIter.next();
        value second = secondIter.next();
        if (!is Finished first, !is Finished second) {
            if (!comparing(first, second)) {
                return false;
            }
        }
        else {
            return first is Finished && second is Finished;
        }
    }
}

"Compares corresponding elements of the given streams using 
 the given [[comparison function|comparing]]. Two elements 
 are considered _corresponding_ if they occupy the same 
 position in their respective streams. Returns:
 
 - the result of the given comparison for the earliest pair
   of corresponding elements whose comparison does not 
   evaluate to [[equal]], or, otherwise, if every comparison 
   of corresponding pairs of elements produces `equal`,
 - [[smaller]], if the first stream produces fewer elements 
   than the second stream, 
 - [[larger]], if the first stream produces more elements 
   than the second stream, or
 - [[equal]] if the two streams produce the same number of 
   elements.
 
 If both streams are empty, return `equal`.
 
 For example:
 
     compareCorresponding({ 1, 2, 2, 5 }, 1:4,
            (Integer i, Integer j) => i<=>j)
 
 and:
 
     compareCorresponding({ 1, 2, 3 }, 1:4,
            (Integer i, Integer j) => i<=>j)
 
 both evaluate to `smaller`."
see (`function corresponding`)
tagged("Comparisons", "Streams")
since("1.3.0")
shared Comparison compareCorresponding<First,Second>(
    {First*} firstIterable, {Second*} secondIterable,
    "The comparison function that compares an element of the
     [[first stream|firstIterable]] with the corresponding 
     element of the [[second stream|secondIterable]]."
    Comparison comparing(First first, Second second)) {
    value firstIter = firstIterable.iterator();
    value secondIter = secondIterable.iterator();
    while (true) {
        value first = firstIter.next();
        value second = secondIter.next();
        if (!is Finished first, !is Finished second) {
            value comp = comparing(first, second);
            if (comp!=equal) {
                return comp;
            }
        }
        else {
            value firstFinished = first is Finished;
            value secondFinished = second is Finished;
            return if (firstFinished && !secondFinished) 
                    then smaller
              else if (!firstFinished && secondFinished) 
                    then larger
              else equal;
        }
    }
}