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

add compare for sorted_set #1470

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

illusory0x0
Copy link
Contributor

No description provided.

Copy link

peter-jerry-ye-code-review bot commented Jan 13, 2025

‼️ This code review is generated by a bot. Please verify the content before trusting it.

Here are three observations and potential issues from the provided git diff:

  1. Potential Issue in compare Implementation:

    • The compare function in set.mbt uses a depth-first search (DFS) approach to compare elements of two sets. However, the DFS traversal might not correctly handle cases where the sets have the same elements but in different orders due to the tree structure. This could lead to incorrect comparison results. For example, if the tree structure is unbalanced, the traversal order might not match the sorted order of the elements, leading to incorrect comparisons.
  2. Redundant Comparison Logic:

    • The compare function includes a fallback comparison based on the sizes of the sets (self.size - other.size). While this is a valid approach, it might be redundant if the DFS traversal already correctly identifies differences in the elements. This redundancy could lead to confusion or inefficiency in the code.
  3. Test Case Coverage:

    • The new test cases in set_test.mbt for the compare function only test basic scenarios (e.g., comparing sets of different sizes). There are no test cases for more complex scenarios, such as comparing sets with the same elements but different tree structures, or comparing sets with elements that are not in the same order. This lack of comprehensive test coverage could miss edge cases where the compare function might fail.

These observations suggest that the compare function might need further refinement and additional test cases to ensure it behaves correctly in all scenarios.

@coveralls
Copy link
Collaborator

coveralls commented Jan 13, 2025

Pull Request Test Coverage Report for Build 4741

Details

  • 9 of 9 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.02%) to 82.867%

Totals Coverage Status
Change from base Build 4739: 0.02%
Covered Lines: 4827
Relevant Lines: 5825

💛 - Coveralls

@bobzhang bobzhang force-pushed the improve-equal-for-sorted_set branch from 867625e to 0a4e9dd Compare January 14, 2025 02:09
@bobzhang
Copy link
Contributor

cc @hackwaly I remember you wrote one reasonably efficient version before?

@hackwaly
Copy link
Contributor

It's there:

pub impl[A : Compare] Compare for T[A] with compare(self, other) -> Int {
let iter = InorderIterator::new(self)
let iter1 = InorderIterator::new(other)
loop iter.next(), iter1.next() {
None, None => 0
Some(a), Some(b) => {
let cmp = a.compare(b)
guard cmp == 0 else { break cmp }
continue iter.next(), iter1.next()
}
Some(_), None => 1
None, Some(_) => -1
}
}

@peter-jerry-ye
Copy link
Collaborator

I think the design principle for comparing containers in core is to compare the size first?

@Lampese
Copy link
Collaborator

Lampese commented Jan 15, 2025

I have one concern: Will structure-based comparisons affect the results of the comparison because of the order in which the nodes are inserted? I'll test that out later.

@hackwaly
Copy link
Contributor

hackwaly commented Jan 15, 2025

I think the design principle for comparing containers in core is to compare the size first?

I don't think so. Usually, String::compare isn't, and Some containers don't have O(1) length at all.

but, here we can compare size first due to performance reason.

@peter-jerry-ye
Copy link
Collaborator

I think the design principle for comparing containers in core is to compare the size first?

I don't think so. Usually, String::compare isn't, and Some containers don't have O(1) length at all.

but, here we can compare size first due to performance reason.

I'm pretty sure we compare string with length first. Also, the length can always be traced for any container.

Comment on lines +327 to +332
dfs(self.root)
if result != 0 {
result
} else {
(self.size - other.size).to_int()
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here we do dfs first and then compare length, which is weird.

@hackwaly
Copy link
Contributor

Also, the length can always be traced for any container.

The case is Iter::compare, and if we gonna to have something like LazySeq.

@peter-jerry-ye
Copy link
Collaborator

peter-jerry-ye commented Jan 15, 2025

Also, the length can always be traced for any container.

The case is Iter::compare, and if we gonna to have something like LazySeq.

Do you mean comparing two Iter? I don't think that's possible with internal iterator, same reason as Iter::zip. As of LazySeq, yeah, that's the only case where we have to compare the elements first. But do we really need that? You might encounter infinite length Seq.

type LazySeq () -> Int?

let a : LazySeq = fn () { Some(5) }
let b : LazySeq = fn () { Some(5) }

let c = a < b // <-- will you ever do that?

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.

6 participants