Skip to content

add @array.zip and @array.zip_with #1575

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Conversation

myfreess
Copy link
Contributor

No description provided.

@coveralls
Copy link
Collaborator

coveralls commented Jan 26, 2025

Pull Request Test Coverage Report for Build 6413

Details

  • 20 of 21 (95.24%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.002%) to 93.255%

Changes Missing Coverage Covered Lines Changed/Added Lines %
array/array.mbt 16 17 94.12%
Totals Coverage Status
Change from base Build 6409: 0.002%
Covered Lines: 5890
Relevant Lines: 6316

💛 - Coveralls

@myfreess myfreess force-pushed the myfreess/add-array-zip branch 2 times, most recently from c82b1f9 to 01aafb4 Compare January 26, 2025 04:46
@myfreess myfreess requested a review from Yoorkin January 26, 2025 06:05
@Lampese
Copy link
Collaborator

Lampese commented Jan 27, 2025

I have an API design concern, with Array zip, what about FixedArray? What about other linearly traversable structures? This leads to the discussion that Iter::zip, but our Iter can't do zip...

cc @bobzhang

@FlammeShadow
Copy link
Contributor

It seems zip_with can be easily composed with zip and map?

@illusory0x0
Copy link
Contributor

related issue.

@Yoorkin
Copy link
Collaborator

Yoorkin commented Feb 18, 2025

There is a zip function in immut/list:

/// Zip two lists.
/// If the lists have different lengths, it will return None.
pub fn zip[A, B](self : T[A], other : T[B]) -> T[(A, B)]?

It's a method that returns an option. To make the API more consistent, consider changing the API like this:

// in immut/list
pub fn zip[A, B](self : T[A], other : T[B]) -> T[(A, B)]

// in array
pub fn zip[A, B](self : T[A], other : T[B]) -> T[(A, B)]
pub fn zip_with[A, B, C](self : T[A], other : T[B], merge~ : (A,B)->C) -> T[C]

@myfreess myfreess force-pushed the myfreess/add-array-zip branch 2 times, most recently from 3c82d74 to eb98c89 Compare February 18, 2025 08:03
@Lampese
Copy link
Collaborator

Lampese commented Feb 18, 2025

I have an API design concern, with Array zip, what about FixedArray? What about other linearly traversable structures? This leads to the discussion that Iter::zip, but our Iter can't do zip...

cc @bobzhang

So that the zip for FixedArray is a todo issue?

Copy link

peter-jerry-ye-code-review bot commented Apr 18, 2025

Different behaviors between Array.zip and List.zip may confuse users

Category
Maintainability
Code Snippet
// Array.zip truncates to shortest length
array1.zip(array2) // Returns [(1,a), (2,b)] for [1,2] and [a,b,c]

// List.zip behavior changed from returning Option to truncating
list1.zip(list2) // Now returns same truncating behavior
Recommendation
Consider adding documentation to explicitly highlight this behavioral change in List.zip, and explain why Option was removed in favor of truncation
Reasoning
The change in List.zip behavior from returning Option to truncating is significant and should be clearly documented. While aligning behavior with Array.zip makes sense for consistency, the change could break existing code that expects an Option return type.

zip_to_iter2 lacks documentation about early termination behavior

Category
Correctness
Code Snippet
pub fn zip_to_iter2[A, B](self : Array[A], other : Array[B]) -> Iter2[A, B] {
// ... if yield_(self[i], other[i]) == IterEnd { break IterEnd } ...
}
Recommendation
Add documentation explaining that iteration can be terminated early if the yield function returns IterEnd
Reasoning
The early termination behavior via IterEnd is an important detail that users should be aware of, as it affects how the iterator can be used in practice

Array capacity pre-allocation could be optimized in zip functions

Category
Performance
Code Snippet
let length = if self.length() < other.length() { self.length() } else { other.length() }
let arr = Array::new(capacity=length)
Recommendation
Consider adding a specialized implementation when arrays have equal length to avoid the length comparison
Reasoning
For the common case where arrays have equal length, we could avoid the length comparison. This could be done via a fast path check: if self.length() == other.length() { ... }

array/array.mbt Outdated
pub fn zip_with[A, B, C](
l : Array[A],
r : Array[B],
merge~ : (A, B) -> C
Copy link
Collaborator

Choose a reason for hiding this comment

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

without labelled argument

Copy link
Collaborator

Choose a reason for hiding this comment

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

Provide zip_to_iter for creating Iter2

@myfreess myfreess force-pushed the myfreess/add-array-zip branch 3 times, most recently from 29bc8d3 to 64f58b6 Compare April 20, 2025 06:47
@myfreess myfreess force-pushed the myfreess/add-array-zip branch from 64f58b6 to 5c8e9b6 Compare April 20, 2025 06:48
Copy link
Collaborator

@peter-jerry-ye peter-jerry-ye left a comment

Choose a reason for hiding this comment

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

drop the changes in immut/list as they are irrelevant and we are going to deprecate them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants