Reputation: 788
How can I make use of functional patterns without incurring in borrowing problems? The solution proposed by the compiler leads to another error (expected array
[u8; 3], found '&[u8]'
) and it goes on from one error to another different error, indefinitely.
Some related code seem overly complicated for such a simple task like in this other question.
use reduce::Reduce;
/// Take an array representing a sequence of 3-tuples and fold it through an arbitrary sandwich logic.
fn sandwich(lst: &[u8])->[u8; 3]{
lst.chunks(3).reduce(|x, y| [x[0], y[1], x[0]]).unwrap()
}
/*
3 | lst.chunks(3).reduce(|x, y| [x[0], y[1], x[0]]).unwrap()
| ^^^^^^^^^^^^^^^^^^
| |
| expected `&[u8]`, found array `[u8; 3]`
| help: consider borrowing here: `&[x[0], y[1], x[0]]`
*/
The best compilable code I could write was this convoluted one, giving up reduce at all:
fn sandwich2(lst: &[u8])->[u8; 3]{
let mut r: [u8; 3] = lst[..].try_into().unwrap();
for i in (3..lst.len()).step_by(3) {
let y = &lst[i..i + 3];
r = [r[0], y[1], r[0]];
}
r
}
Please note that sandwich is just an example to illustrate the problem (that does nothing actually smart). I expect an external much more complex function instead of that lambda.
Upvotes: 1
Views: 389
Reputation: 42708
You have to somehow take ownership of the values into a required [u8; 3]
.
Maybe as this example using the iterator_fold_self
feature (as per today nightly):
#![feature(iterator_fold_self)]
/// Take an array representing a sequence of 3-tuples and reduce it through an arbitrary sandwich logic.
fn sandwich(lst: &[u8]) -> [u8; 3] {
lst.chunks(3)
.map(|x| [x[0], x[1], x[2]])
.reduce(|x, y| [x[0], y[1], x[0]])
.unwrap()
}
fn main() {
let test_set = [1, 2, 3, 1, 2, 3];
println!("{:?}", sandwich(&test_set));
}
You can use try_into
(from this famous answer) to get an owned slice:
fn sandwich(lst: &[u8]) -> [u8; 3] {
lst.chunks(3)
.map(|x| -> [u8; 3] { x.try_into().unwrap() } )
.reduce(|x, y| [x[0], y[1], x[0]])
.unwrap()
}
Upvotes: 1