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

Implement missing imperative Set functions #168

Merged
merged 13 commits into from
Feb 24, 2025
Merged

Implement missing imperative Set functions #168

merged 13 commits into from
Feb 24, 2025

Conversation

rvanasa
Copy link
Collaborator

@rvanasa rvanasa commented Feb 21, 2025

Adds the following functions to the Set module:

@rvanasa rvanasa requested a review from a team as a code owner February 21, 2025 00:26
Copy link

github-actions bot commented Feb 21, 2025

No description provided.

Copy link
Contributor

@crusso crusso left a comment

Choose a reason for hiding this comment

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

Curious, why do these take iterators not sets? For example, I think retainAll might be simpler and more efficient if you were given a set.

Don't go and rewrite. I'm just asking.

@rvanasa
Copy link
Collaborator Author

rvanasa commented Feb 21, 2025

Curious, why do these take iterators not sets? For example, I think retainAll might be simpler and more efficient if you were given a set.

The idea is for these functions to have a consistent API if we eventually include them for other data structures. Perhaps we could have unionInPlace(), intersectInPlace(), etc. (or whatever we'd like to name them) for better performance in the case of having two Set values. If we do that, we could maybe even just remove the retainAll() function given that it's a fairly niche use case.

src/Set.mo Outdated
/// where `m` and `n` denote the number of values in `set` and `iter`, respectively,
/// and assuming that the `compare` function implements an `O(1)` comparison.
public func retainAll<T>(set : Set<T>, compare : (T, T) -> Order.Order, iter : Types.Iter<T>) {
// TODO: optimize?
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, this looks quadratic to me.

a simple improvement might be to construct a local Set from iter so you can use contains not linear search for testing common membership.
Also setList could just be created as an ordinary array since we know the size of set up-front. Probably cheaper.

Copy link
Collaborator Author

@rvanasa rvanasa Feb 21, 2025

Choose a reason for hiding this comment

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

I noticed that Rust, Kotlin, and a few other languages use a predicate instead of collection as an argument to this function, which seems both more flexible and better for performance. I'll update the PR to go with this, and we can revise from there.

Copy link
Collaborator Author

@rvanasa rvanasa Feb 22, 2025

Choose a reason for hiding this comment

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

Updated, although it's a bit wonky having to pass both the compare and predicate functions. Perhaps this is another reason for prioritizing dataclasses or another language feature to remove those as soon as possible (before merging this into dfinity/motoko-base).

@rvanasa rvanasa enabled auto-merge (squash) February 24, 2025 20:36
/// Set.add(set, Nat.compare, 2);
/// Set.add(set, Nat.compare, 3);
/// let pureSet = Set.toPure(set);
/// assert(PureSet.contains(pureSet, 1));
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// assert(PureSet.contains(pureSet, 1));
/// assert(PureSet.contains(pureSet, Nat.compare, 1));

/// pureSet := PureSet.add(pureSet, Nat.compare, 2);
/// pureSet := PureSet.add(pureSet, Nat.compare, 3);
/// let mutableSet = Set.fromPure(pureSet);
// assert(Set.contains(mutableSet, 1));
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// assert(Set.contains(mutableSet, 1));
// assert(Set.contains(mutableSet, Nat.compare, 1));

@@ -69,11 +69,11 @@ module {
todo()
};

public func intersect<T>(set1 : Set<T>, set2 : Set<T>) : Set<T> {
public func intersection<T>(set1 : Set<T>, set2 : Set<T>) : Set<T> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'll rename in my branch too.

todo()
};

public func diff<T>(set1 : Set<T>, set2 : Set<T>) : Set<T> {
public func difference<T>(set1 : Set<T>, set2 : Set<T>) : Set<T> {
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto

todo()
};

public func diff<T>(set1 : Set<T>, set2 : Set<T>) : Set<T> {
public func difference<T>(set1 : Set<T>, set2 : Set<T>) : Set<T> {
Copy link
Contributor

@crusso crusso Feb 24, 2025

Choose a reason for hiding this comment

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

Suggested change
public func difference<T>(set1 : Set<T>, set2 : Set<T>) : Set<T> {
public func difference<T>(set1 : Set<T>, set2 : Set<T>, compare : (T, T) -> Types.Order) : Set<T> {

@@ -69,11 +69,11 @@ module {
todo()
};

public func intersect<T>(set1 : Set<T>, set2 : Set<T>) : Set<T> {
public func intersection<T>(set1 : Set<T>, set2 : Set<T>) : Set<T> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public func intersection<T>(set1 : Set<T>, set2 : Set<T>) : Set<T> {
public func intersection<T>(set1 : Set<T>, set2 : Set<T>, compare: (T, T) -> Types.Order) : Set<T> {

@rvanasa rvanasa merged commit 603d531 into main Feb 24, 2025
8 checks passed
@rvanasa rvanasa deleted the set-misc branch February 24, 2025 20:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants