Repository navigation
Tracking Issue for split_array #90091
Copy link
Copy link
Open
Labels
A-arrayArea: `[T; N]`Area: `[T; N]`C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Description
Feature gate: #![feature(split_array)]
This is a tracking issue for splitting slices and arrays into constant-length arrays.
Public API
impl<T, const N: usize> [T; N] {
pub fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T]);
pub fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T]);
pub fn rsplit_array_ref<const M: usize>(&self) -> (&[T], &[T; M]);
pub fn rsplit_array_mut<const M: usize>(&mut self) -> (&mut [T], &mut [T; M]);
}Similar functions for slices have already been stabilized as:
impl [T] {
pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])>;
pub fn split_first_chunk_mut<const N: usize>(&mut self) -> Option<(&mut [T; N], &mut [T])>;
pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T], &[T; N])>;
pub fn split_last_chunk_mut<const N: usize>(&mut self) -> Option<(&mut [T], &mut [T; N])>;
}See #111774
Unresolved Questions
- Naming, see Implement split_array and split_array_mut #83233 (review)
- Array functions should return
[T; N - M], like so:
impl<T, const N: usize> [T; N] {
pub fn split_array<const M: usize>(self) -> ([T; M], [T; N - M]);
pub fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T; N - M]);
pub fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T; N - M]);
}However, const generics is not powerful enough for this today. See #83233 (comment) and #83233 (comment).
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
A-arrayArea: `[T; N]`Area: `[T; N]`C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Activity
jdahlstrom commentedon Oct 28, 2021
Hmm. Panicking if
M > slice.len(), rather than returning aResult/Option, seems a bit surprising to me. I guess it's consistent withsplit_at, but on the other hand inconsistent with eg.split_first.scottmcm commentedon Dec 3, 2021
For the slice versions of these, I think it's important that they not only offer
-> (&[T; N], &[T]), but also-> (&[T], &[T; N]). (This is basically the same as how there's bothas_chunksandas_rchunks, see #78818.)That might open up new naming possibilities too. To spitball:
split_prefix: &[T] -> (&[T; N], &[T])andsplit_suffix: &[T] -> (&[T], &[T; N])jplatte commentedon Dec 4, 2021
I agree that should exist, but I think it should be named
rsplit_arraysince there's already a bunch of split functions whose "from the end" variations are all calledrsplit*.yaahc commentedon Dec 10, 2021
I'd argue for local consistency over global consistency. In the case of slice we already have methods following both conventions, but the methods following the
_prefix_suffixconvention are related to stripping, where as the split methods all currently follow thesplitrsplitconvention, so I lean towards keeping the current names.Rollup merge of rust-lang#91515 - jethrogb:rsplit_array, r=yaahc
jethrogb commentedon Dec 27, 2021
Should there also be a shorthand API for
slice[a..].split_array_ref::<B>()(the array version of&slice[a..(a+B)])?pmnoxx commentedon Jan 16, 2022
I think that the result should be an Option. This would allow us to properly handle splitting in case, the number of elements is lesser than the given contant.
I've been looking an api like that. However, it would be great to add a proper handling of cases, where split can't happen.
Consider
jethrogb commentedon Jan 16, 2022
split_atdoesn't return anOption.pmnoxx commentedon Jan 16, 2022
Yes, that's unfortunate. I think it would be great to add
try_split_atapi. This would simplify at lot of code.For example:
Currently, I have to write code like this to use the api:
I think it would be much cleaner to write it in a declarative way, which avoid hidden unwraps of getting a slice.
Or even better
scottmcm commentedon Mar 22, 2022
cc #95198, which proposes doing this more like the
split_firstfamily of things.Those naturally would return
Option, the same way thatfirst&split_firstreturnOptiontoday.faern commentedon Apr 7, 2022
I definitely want infallible (fail at compile time) split methods on arrays. I want to be able to cut arrays up into smaller array chunks without any bounds checks at runtime. I know there are issues currently that won't allow this API today. But I think we should aim for a future where we can do that.
Being able to parse the content of arrays without paying more bounds checks or code bloat than needed is definitely desired both for readability and performance.
([0u8; 100]).split_array_ref::<10>().expect("out of bounds, will never happen)does not look nice and has a lot of code paths that we already know won't happen. If it was a compile time error we would not accidentally create bugs where the10was made into a too large number.faern commentedon Apr 7, 2022
This makes no sense IMO 🤔 Because the only time it would ever be
Noneshould be found at compile time. I know that's not possible now. But why introduce a large API surface and use up a bunch of good method names for something that's (hopefully)? a temporary limitation.Xiretza commentedon May 18, 2022
I agree with the comments above that the methods on
&[T]should returnOptions, but as @faern said this makes no sense on arrays, where all size checks are known at compile time. In my opinion the API would ideally look like this (note also thersplit_methods on arrays, for completeness):But as noted in the OP, this requires more advanced const generics features. The alternative array API (returning slices for the "rest") would be possible today, but I think it'd be better to wait until the "proper" solution is possible rather than stabilizing something suboptimal.
23 remaining items
scottmcm commentedon Jan 11, 2024
With those methods in FCP (#117561 (comment)), nominating this one for libs-api to consider whether they'd like to see these ones deleted from nightly.Err, I should read better. https://github.com/rust-lang/rust/pull/117561/files#diff-e8ccaf64ce21f955ccebef33b52158631493a6f0966815a2ebc142d7cd2b5e06L2024 is removing these methods.
Rollup merge of rust-lang#117561 - tgross35:split-array, r=scottmcm
Unrolled build for rust-lang#117561
tgross35 commentedon Jan 20, 2024
This should be reopened, I'm not sure why #117561 closed it. Also the tracking issue can be updated to remove the
impl<T> [T]block, #117561 removed it (and stabilized theslice_first_last_chunkin its place, yay!)scottmcm commentedon Jan 20, 2024
Oh, that's my fault -- I saw that it removed
split_array_refand such and thought it was everything.tgross35 commentedon Jan 20, 2024
Oh, no I only removed the slice components. I know we want a different API but figured that would just be a rework of this implementation.
But maybe it’s better to start something new with a clean tracking history. I can submit a PR to remove if so.
Rollup merge of #117561 - tgross35:split-array, r=scottmcm
tgross35 commentedon Jan 21, 2024
Haven't seen it linked here, the
arrayrefcrate provides a way to do this.