-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Tracking Issue for array_zip
#80094
Comments
Could you show two use cases? |
What made me open the PR was for doing element wise operations on vector-like objects without the need for any heap allocations or unnecessary zeroing. struct Vector([T; N]);
impl Add<Vector> for Vector {
fn add(self, rhs: Vector) -> Vector {
self.0.zip(rhs.0).map(|(lhs, rhs)| lhs + rhs)
}
} As for a second use case, well I will have to think about that one... Maybe bit far-fetched but here goes: const RES: usize = WIDTH * HEIGHT;
fn compute_pixels_for_screen_on_embedded_thing(
background: [ImgColor; RES],
object: [ImgColor; RES]
) -> [ScreenColor; RES] {
background.zip(object).map(magic_color_mix)
} (which I suppose is pretty much the same use case but with different names) |
Wouldn't this become obsolete after #65798? |
No because iterators don't encode the length in the type, so if you intend to go back to an array you'd have to unwrap. |
Can't we give arrays a different iterator that encodes the length too? :-) |
Wouldn't that be problematic in combination with methods like |
Yeah. We can't have a "filter" there. So only some iterators are possible. But "skip" is doable as long as the number of items to skip is given as a const generics value (and in my code the argument of "skip" is often a value known at compile-time). |
Would that be/work with #80470 or something completely different like new trait? Just asking since it seems like |
I have started doing some experimenting here. Atleast to me this feels like a much more reusable and flexible solution than adding all of those of methods directly to |
As somebody who has stumbled upon this unstable method while implementing some const generic vector operations, I would like to point out something regarding the presented use case. To actually efficiently lift traits like |
@MDoerner any thoughts on something like iter_fixed? Edit: There is an example here for vector addition let x = [1, 2, 3];
let y = [4, 5, 6];
let z: [_; 3] = x
.into_iter_fixed()
.zip(y)
.map(|(a, b)| a + b)
.collect(); |
This method has ended up being incredibly useful in my fixed-array audio DSP library, mainly in frame addition/multiplication. It allows me to do an element-wise binary operation without needing to use iterators (non-const? pah!) or having to create an incrementally-updated output array. The latter is especially nice in cases where the output type is expensive to instantiate: having to create Something I'd love to suggest would be a corresponding impl<T, U, const N: usize> [(T, U); N] {
fn unzip(self) -> ([T; N], [U; N]) {
// impl
}
} I'd be happy to work on an impl of |
@usbalbin can we get rid of |
The problem is that regular Note however that |
hmm, yes it looks impossible. I was dreaming of an iterator with a |
I think such a fixed iterator would have to implement a separate iterator trait, but that trait could have a method that converts it into a normal iterator. For instance, the fixed iterator could have methods that operate on it that transform it from one fixed length to another, and it could lazily evaluate to an array (no // Note that an array would implement the fixed iterator trait (output equals the array itself).
let arr = [1, 2, 3];
// You could use the map method to change the array values.
let mapped = arr.map(|v| v*2);
// Then you could either turn the mapped fixed iterator into an array
let double_arr: [i32; 3] = mapped.array();
// or you could turn it into an iterator (note that the iterator values are of type `i32`, not `&i32`).
let sum: i32 = mapped.iter().sum();
// Note that it was used a second time here because the mapped array implements `Copy`. |
Now that method needs to be named something like "lazy_map()" |
@leonardo-m Yes, I suppose it is too late to create a lazy array trait with a |
In #103555 Does anyone actually need the |
Potential concern: overlap with potential
|
This comment was marked as off-topic.
This comment was marked as off-topic.
So, I'll repeat my previous question: Is there anyone who's in favor of keeping |
@the8472 see my earlier comment, do you have any thoughts on that? Edit: Just saw you mentioned it earlier. |
Nominating this for removal since |
@rfcbot close |
Team member @m-ou-se has proposed to close this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
FWIW, this now at least codegens decently well for basic cases. For example, rust/tests/codegen/array-map.rs Lines 21 to 27 in 669e751
But I do also think that a |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
The final comment period, with a disposition to close, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. |
Remove array_zip `[T; N]::zip` is "eager" but most zips are mapped. This causes poor optimization in generated code. This is a fundamental design issue and "zip" is "prime real estate" in terms of function names, so let's free it up again. - FCP concluded in rust-lang/rust#80094 (comment) - Closes rust-lang/rust#80094 - Closes rust-lang/rust#103555 Could use review to make sure we aren't losing any essential codegen tests. r? `@scottmcm`
Feature gate:
#![feature(array_zip)]
This is a tracking issue for the
zip
method on arrays.Just like
Iterator::zip
combines two iterators into one,[T; N]::zip()
returns a new array where every element is a tuple where the first element comes from the first array, and the second element comes from the second array. In other words, it zips two arrays together, into a single one.Public API
Steps / History
Unresolved Questions
@cramertj comment
@yoshuawuyts comment
The text was updated successfully, but these errors were encountered: