Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Predicate versions of allequal & allunique #47679

Merged
merged 8 commits into from
Feb 11, 2024

Conversation

mcabbott
Copy link
Contributor

@mcabbott mcabbott commented Nov 23, 2022

Closes #47005, and does the same for allunique.

First, a33ac25 uses Iterators.peel to improve allequal(itr) as suggested by @jlapeyre in here: #47005 (comment) .

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 times a few variants.

base/set.jl Outdated Show resolved Hide resolved
test/sets.jl Outdated Show resolved Hide resolved
@brenhinkeller brenhinkeller added iteration Involves iteration or the iteration protocol feature Indicates new feature / enhancement requests labels Nov 23, 2022
base/set.jl Outdated
@@ -425,11 +425,16 @@ end

"""
allunique(itr) -> Bool
allunique(f, xs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very nitpicky, but using different names for the iterator seems confusing (even though it's maybe helpful for the current definition of this second form).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a bit ugly, I think I wanted to say itr = (f(x) for x in xs) below... but can say it another way.

Think it's OK to roll these definitions into the same docstring? They could be separate but probably that's just more text to dig through.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See if you like 21961ec

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes looks good. An alternative could be

""""
    allunique([f=identity], itr) -> Bool

Return `true` if all values from `(f(x) for x in itr)` are distinct when compared with [`isequal`](@ref).
"""

(but that makes the simpler case (allunique(itr)) more difficult to understand...)

Copy link
Contributor Author

@mcabbott mcabbott Jan 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it should warn you that how many times f is called is regarded as an implementation detail? It may not be called at all (if length 1 is known) and it may be called even after a non-unique elements has been seen (as _indexed_allunique(collect(C)) makes the whole array & then checks).

Not sure how surprising that is. In my head at least, f ought to be fairly cheap, because you are obviously throwing away what it returns, and probably pure too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

724f048 adds such a note.

base/set.jl Show resolved Hide resolved
@3f6a
Copy link

3f6a commented Aug 2, 2023

Would be nice to have this. Is there something missing on this PR, or is this ready to be merged?

@mcabbott
Copy link
Contributor Author

Pre-1.11 bump?

@vtjnash vtjnash merged commit efa77cc into JuliaLang:master Feb 11, 2024
5 of 7 checks passed
@vtjnash
Copy link
Member

vtjnash commented Feb 11, 2024

LGTM. I polished up the commit message a bit on merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Indicates new feature / enhancement requests iteration Involves iteration or the iteration protocol
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Predicate version of allequal
8 participants