为什么 Rust 的 ChunksExact<T> 在编译时没有已知的大小
Why doesn't Rust's ChunksExact<T> have a size known at compile-time
我想将一个 Vec
复制到另一个,在 [u8; 4]
的 块 中分配第一个 3 仅每个块的元素(仅保留第 4 个)。这似乎是一种实用的方法:
let input_pix: Vec<u8> = ...;
let mut output_pix: Vec<u8> = vec![255; input_pix.len()];
for (input_chunk, output_chunk) in input_pix.chunks(4).zip(output_pix.chunks_exact_mut(4)) {
let i: u8 = foo(...);
output_chunk[0..2].clone_from_slice([i,3]);
}
...但是 编译器不喜欢它。事实上 slicing output_chunk
完全会抛出错误。最简单:
...
for (input_chunk, output_chunk) in input_pix.chunks(4).zip(output_pix.chunks_exact_mut(4)) {
let s = format!("{:?}", output_chunk[0..2]);
}
结果...
|
40 | let s = format!("{:?}", output_chunk[0..2]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
来自文档:
The chunks are slices and do not overlap. If chunk_size does not
divide the length of the slice, then the last up to chunk_size-1
elements will be omitted and can be retrieved from the remainder
function of the iterator.
Due to each chunk having exactly chunk_size elements, the compiler can
often optimize the resulting code better than in the case of chunks.
所以...似乎是说 ChunksExactMut
(从 chunks_exact_mut
返回)的元素大小是准确的,在这种情况下 4,那又是什么呢?在编译时知道大小感觉有点像点 of ChunksExactMut
.
我走错路了吗?是否有一些更惯用的方法来复制到 ChunksExactMut
的一片中。我可以简单地通过循环复制元素,但这看起来很臭。或者也许是做这件事的方法,我应该让编译器完成工作?
TL;DR: 只需将其更改为
let s = format!("{:?}", &output_chunk[0..2]);
// ^^^ the important bit
按范围索引切片(&[T]
类型)时,return 类型为 [T]
。调整大小是 属性 类型而不是 属性 值。因此,即使我们使用已知宽度(即 0..2
)进行索引,我们仍然会得到一个未调整大小的类型作为输出。
未调整大小的一个缺点是该类型的值无法传递给函数。因此,为了将这种类型的元素格式化为字符串,我们必须传递一个指针。最简单的方法就是简单地借用切片。
无效:
fn foo(slice: &[u8]) -> String {
format!("{:?}", slice[0..2])
}
有效:
fn foo(slice: &[u8]) -> String {
format!("{:?}", &slice[0..2])
}
我想将一个 Vec
复制到另一个,在 [u8; 4]
的 块 中分配第一个 3 仅每个块的元素(仅保留第 4 个)。这似乎是一种实用的方法:
let input_pix: Vec<u8> = ...;
let mut output_pix: Vec<u8> = vec![255; input_pix.len()];
for (input_chunk, output_chunk) in input_pix.chunks(4).zip(output_pix.chunks_exact_mut(4)) {
let i: u8 = foo(...);
output_chunk[0..2].clone_from_slice([i,3]);
}
...但是 编译器不喜欢它。事实上 slicing output_chunk
完全会抛出错误。最简单:
...
for (input_chunk, output_chunk) in input_pix.chunks(4).zip(output_pix.chunks_exact_mut(4)) {
let s = format!("{:?}", output_chunk[0..2]);
}
结果...
|
40 | let s = format!("{:?}", output_chunk[0..2]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
来自文档:
The chunks are slices and do not overlap. If chunk_size does not divide the length of the slice, then the last up to chunk_size-1 elements will be omitted and can be retrieved from the remainder function of the iterator.
Due to each chunk having exactly chunk_size elements, the compiler can often optimize the resulting code better than in the case of chunks.
所以...似乎是说 ChunksExactMut
(从 chunks_exact_mut
返回)的元素大小是准确的,在这种情况下 4,那又是什么呢?在编译时知道大小感觉有点像点 of ChunksExactMut
.
我走错路了吗?是否有一些更惯用的方法来复制到 ChunksExactMut
的一片中。我可以简单地通过循环复制元素,但这看起来很臭。或者也许是做这件事的方法,我应该让编译器完成工作?
TL;DR: 只需将其更改为
let s = format!("{:?}", &output_chunk[0..2]);
// ^^^ the important bit
按范围索引切片(&[T]
类型)时,return 类型为 [T]
。调整大小是 属性 类型而不是 属性 值。因此,即使我们使用已知宽度(即 0..2
)进行索引,我们仍然会得到一个未调整大小的类型作为输出。
未调整大小的一个缺点是该类型的值无法传递给函数。因此,为了将这种类型的元素格式化为字符串,我们必须传递一个指针。最简单的方法就是简单地借用切片。
无效:
fn foo(slice: &[u8]) -> String {
format!("{:?}", slice[0..2])
}
有效:
fn foo(slice: &[u8]) -> String {
format!("{:?}", &slice[0..2])
}