I know the topic has been addressed before, but since the subject has been closed I'm writing here.
Is there any reason why slice and index doesn't have optional or result as return type?
I know this might give a little overhead where it can't be optimized out, but since rust allow destructive pattern matching it could defiantly improve the readability and case analysis of control flow.
as an example assume we are processing some slice arr of u8, we which test against that the second element from start position are of value x.
as of now this would be
if arr.len() >= 3 {
if arr[1] == x {
// do case 1
} else {
// do case 2
}
} else {
// do case 2
}
if it returned a result type it would look like this
if let Ok([a,x,b]) = arr[0..3] { // where a and b are casting values, and x are the pattern from before
// do case 1 with a and b
} else {
// do case 2
}
I use the function
pub const fn try_slice<T>(content: &[T], from: usize, to: usize) -> Option<&[T]> {
if content.len() >= to && from <= to {
Some(&content[from..to])
} else {
// this will most likely be optimized away by the compiler
// since this is only to catch none accepted patterns
None
}
}
where the None case most likely would be optimized away, and generate better performing code because of less branching.
we could still pattern match the error cases if needed, but they could be contrained to an easy matchable Error set, instead of just panicking. if we want the current behavior it is just to unwrap the return value with the operator ? and it will still panic. when it comes to implementation in the compiler it should not impose any new problems with current pointer and boundary optimizations.
It would most defiantly make programmers remember index checking when slicing and indexing since it then will be moved into a place where the intellisense could catch it. it will also make library miss use harder and the API better, since you as an implementer could constraint the possible output to a finite set.
Coming from SML and F# where you can do destructive case matching on size directly like
match arr {
[a] => // do something with a,
[a,b] => // do something else,
.....
}
This destructive patterns make sense. I know that the last one most likely would not conform to 'the zero cost abstraction' and I can live with not having this.