Skip to content

Tracking Issue for array_zip #80094

Closed

Description

@usbalbin

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.

let x = [1, 2, 3];
let y = [4, 5, 6];
let z = x.zip(y);
assert_eq!(z, [(1, 4), (2, 5), (3, 6)]);

Public API

pub fn zip<U>(self, rhs: [U; N]) -> [(T, U); N]

Steps / History

Unresolved Questions

@cramertj comment

[...] This seems like a pretty niche feature to me personally, but I can understand that there are situations when you might want it. I'm not sure if the libs team has a standard for "fill in the missing methods" PRs like this.

@yoshuawuyts comment

overlap with potential std::iter::Zip trait [...]

Activity

  1. added
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    T-libs-api[DEPRECATED; DO NOT USE]
    on Dec 16, 2020
  2. leonardo-m commented on Dec 16, 2020

    @leonardo-m

    Could you show two use cases?

  3. usbalbin commented on Dec 16, 2020

    @usbalbin
    ContributorAuthor

    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)

  4. cauebs commented on Dec 21, 2020

    @cauebs
    Contributor

    Wouldn't this become obsolete after #65798?

  5. CryZe commented on Dec 21, 2020

    @CryZe
    Contributor

    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.

  6. leonardo-m commented on Dec 21, 2020

    @leonardo-m

    No because iterators don't encode the length in the type,

    Can't we give arrays a different iterator that encodes the length too? :-)

  7. usbalbin commented on Dec 22, 2020

    @usbalbin
    ContributorAuthor

    No because iterators don't encode the length in the type,

    Can't we give arrays a different iterator that encodes the length too? :-)

    Wouldn't that be problematic in combination with methods like filter or skip etc?

  8. leonardo-m commented on Dec 22, 2020

    @leonardo-m

    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).

  9. usbalbin commented on Jan 2, 2021

    @usbalbin
    ContributorAuthor

    No because iterators don't encode the length in the type,

    Can't we give arrays a different iterator that encodes the length too? :-)

    Would that be/work with #80470 or something completely different like new trait? Just asking since it seems like array IntoIter might be getting stabilized

  10. added
    I-libs-radarLibs issues that are tracked on the team's radar.
    on Jan 6, 2021
  11. usbalbin commented on Mar 1, 2021

    @usbalbin
    ContributorAuthor

    @leonardo-m

    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).

    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 [T; N].

  12. MDoerner commented on May 6, 2021

    @MDoerner

    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 Add as component-wise operations, one would rather need a zip_with operation combining zip and map, maybe with some other name more consistent with rust conventions. Using the unstable array_map from #75243 on array_zip would potentially write the array twice, at least given the current implementation.

  13. usbalbin commented on May 6, 2021

    @usbalbin
    ContributorAuthor

    @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();
  14. linclelinkpart5 commented on Jun 20, 2021

    @linclelinkpart5

    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 N instances for a temporary output buffer that are immediately going to be overwritten is wasteful.

    Something I'd love to suggest would be a corresponding unzip method, the inverse operation of zip. I imagine its signature looking like something along the lines of:

    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 unzip if others think it would be a useful method. I'd personally find quite a few good spots to use this in that DSP library.

  15. 28 remaining items

  16. removed
    proposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
    on Mar 28, 2023
  17. rfcbot commented on Mar 28, 2023

    @rfcbot

    🔔 This is now entering its final comment period, as per the review above. 🔔

  18. added
    proposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
    final-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.
    and removed
    final-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.
    proposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
    on Mar 28, 2023
  19. added and removed
    final-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.
    on Apr 7, 2023
  20. rfcbot commented on Apr 7, 2023

    @rfcbot

    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.

  21. added a commit that references this issue on May 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-arrayArea: `[T; N]`C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCI-libs-radarLibs issues that are tracked on the team's radar.T-libs-api[DEPRECATED; DO NOT USE]disposition-closeThis PR / issue is in PFCP or FCP with a disposition to close it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions