Почему Rust's ChunksExact <T>не имеет размера, известного во время компиляции - PullRequest
1 голос
/ 29 февраля 2020

Я хотел бы скопировать один Vec в другой, в чанках из [u8; 4], назначив первый элемент 3 только для каждого чанка (оставив только 4-й). Это похоже на практический способ go об этом:

    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]);
    }

... НО компилятору это не нравится. На самом деле нарезка 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

Из документов:

Чанки являются кусочками и не перекрываются. Если chunk_size не делит длину среза, то последние до элементов chunk_size-1 будут опущены и могут быть извлечены из функции остатка итератора.

Из-за того, что каждый блок имеет точно элементы chunk_size, компилятор часто может оптимизировать полученный код лучше, чем в случае кусков.

Итак ... похоже, он говорит о размере элементов ChunksExactMut (возвращено из chunks_exact_mut) является точным и в этом случае 4 , так что дает? Зная размер во время компиляции, вы чувствуете, как будто это точка из ChunksExactMut.

Я поступаю неправильно? Есть ли еще какой-то идиоматический c способ скопировать в кусочек ChunksExactMut. Я могу просто скопировать элемент с помощью al oop, но это кажется очень вонючим. Или, может быть, IS способ сделать это, и я должен позволить компилятору сделать работу?

1 Ответ

1 голос
/ 29 февраля 2020

TL; DR: просто измените его на

let s = format!("{:?}", &output_chunk[0..2]);
//                     ^^^ the important bit

При индексации фрагмента (типа &[T]) по диапазону тип возвращаемого значения [T]. Измерение - это свойство типа, а не свойство значений. Поэтому, даже если мы выполняем индексирование с известной шириной (т. Е. 0..2), мы по-прежнему получаем тип без размера в качестве выходного.

Недостатком нестандартного размера является то, что значения этого типа нельзя передавать в функции. Таким образом, чтобы отформатировать элементы такого типа, как строка, мы должны передать указатель. Самый простой способ сделать это - просто позаимствовать ломтик.

Не работает:

fn foo(slice: &[u8]) -> String {
    format!("{:?}", slice[0..2])
}

Работает:

fn foo(slice: &[u8]) -> String {
    format!("{:?}", &slice[0..2])
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...