
public import sequences.force.*;
public import sequences.lazy.*;



//
// strict wrappers around lazy sequences
//

alias zip(..args) = force(zipped(..args));
alias map(..args) = force(mapped(..args));
alias filter(..args) = force(filtered(..args));
alias enumerate(..args) = force(enumerated(..args));
alias reverse(..args) = force(reversed(..args));
alias slice(..args) = force(sliced(..args));
alias sliceFrom(..args) = force(slicedFrom(..args));
alias sliceUpto(..args) = force(slicedUpto(..args));
alias group(..args) = force(grouped(..args));



//
// generic equals?, lesser?
//

[A,B | Sequence?(A) and Sequence?(B)]
overload equals?(a:A, b:B) {
    var i, j = iterator(a), iterator(b);
    while (hasNext?(i)) {
        if (not hasNext?(j))
            return false;
        if (next(i) != next(j))
            return false;
    }
    return not hasNext?(j);
}

[A,B | SizedSequence?(A) and SizedSequence?(B)]
overload equals?(a:A, b:B) {
    if (size(a) != size(b))
        return false;
    var i, j = iterator(a), iterator(b);
    while (hasNext?(i)) {
        if (next(i) != next(j))
            return false;
    }
    return true;
}


[A,B | Sequence?(A) and Sequence?(B)]
overload lesser?(a:A, b:B) {
    var i, j = iterator(a), iterator(b);
    while (hasNext?(i)) {
        if (not hasNext?(j))
            return false;
        forward x, y = next(i), next(j);
        if (x != y)
            return x < y;
    }
    return hasNext?(j);
}



//
// concatenation
//

[A, B | Sequence?(A) and Sequence?(B)
        and (SequenceElementType(A) == SequenceElementType(B))]
overload add(forward a:A, forward b:B) {
    var result = Vector(a);
    push(result, b);
    return move(result);
}

[A, T | Sequence?(A) and (SequenceElementType(A) == T)]
overload add(forward a:A, forward x:T) {
    var result = Vector(a);
    push(result, x);
    return move(result);
}

[A, T | Sequence?(A) and (SequenceElementType(A) == T)]
overload add(forward x:T, forward a:A) = Vector[T](x) + a;


//
// interleave
//

[S | Sequence?(S)]
interleave(seq:S, betweenFn, fn) {
    var i = iterator(seq);
    if (hasNext?(i)) {
        fn(..next(i));
        while (hasNext?(i)) {
            betweenFn();
            fn(..next(i));
        }
    }
}
