Predicate versions of `allequal` & `allunique` (#47679)
First, use `Iterators.peel` to improve `allequal(itr)` as suggested by
jlapeyre in here:
https://github.com/JuliaLang/julia/issues/47005#issuecomment-1276477572
After that, `allequal(f, xs) = allequal(f(x) for x in xs)` should never
call `f` twice on the same `x`, nor more times than necessary.
For `allunique`, at present this has a path which collects short
iterators (<32) as this is faster than making a `Set`. Thus calling
`allunique(f(x) for x in xs)` will sometimes call `f` more times than it
has to. This PR doesn't change that, just adds a method
`allunique(f, xs)`.
Since generators tend to have eltype `Any`, it pays to use
`Set{@default_eltype(C)}()` now. I think this ought to be safe.
Finally, methods `allequal(f, xs::Tuple)` and `allunique(f, xs::Tuple)`
seem to be worthwhile. [This
gist](https://gist.github.com/mcabbott/69c0b85cdf0a37d97eecba3edb18bdc0)
times a few variants.
Closes #47005, and does the same for `allunique`