Я изучаю Rust. Я считаю, что "чрезмерно инженерные" игрушечные примеры полезны на ранних этапах, что и привело меня к этой ситуации.
Начиная с этой простой функции:
extern crate data_encoding;
use std::ops::BitXor;
use data_encoding::hex;
use std::iter::FromIterator;
fn fixed_xor_basic(l: &[u8], r: &[u8]) -> Vec<u8> {
l.iter().zip(r.iter()).map(|(x, y)| *x ^ *y).collect()
}
#[test]
fn test_fixed_xor_basic() {
let input_1 = hex::decode(b"1C0111001F010100061A024B53535009181C").unwrap();
let input_2 = hex::decode(b"686974207468652062756C6C277320657965").unwrap();
let expected_output = hex::decode(b"746865206B696420646F6E277420706C6179").unwrap();
assert_eq!(fixed_xor_basic(&input_1, &input_2), expected_output);
}
Я перешел к простому варианту избавления от распределения:
fn fixed_xor_basic_inplace(l: &mut [u8], r: &[u8]) {
for (left, right) in l.iter_mut().zip(r.iter()) {
*left = *left ^ *right;
}
}
И еще один, который принимает любой тип, который можно использовать XOR:
fn fixed_xor_generic<T>(l: &[T], r: &[T]) -> Vec<T>
where T: BitXor + Copy,
Vec<T>: FromIterator<<T as BitXor>::Output> {
l.iter().zip(r.iter()).map(|(x, y)| *x ^ *y).collect()
}
Этот второй вариант изначально не компилировался, но сообщение об ошибке подсказало мне, что нужно добавить ограничение Vec<T>: FromIterator<<T as BitXor>::Output>
. По-видимому, это ограничение дало компилятору некоторый намек на то, что BitXor::Output
на самом деле то же самое, что и T
, но я не понимаю, что именно это подсказка.
Теперь ... объединение этих двух вещей поставило меня в тупик:
fn fixed_xor_generic_inplace<T>(l: &mut [T], r: &[T])
where T: BitXor + Copy {
for (left, right) in l.iter_mut().zip(r.iter()) {
*left = *left ^ *right;
}
}
Выдает ошибку:
error[E0308]: mismatched types
--> src/xor_lib.rs:27:17
|
27 | *left = *left ^ *right;
| ^^^^^^^^^^^^^^ expected type parameter, found associated type
|
= note: expected type `T`
= note: found type `<T as std::ops::BitXor>::Output`
error: aborting due to previous error
Я сильно подозреваю, что эти две ситуации похожи и что мне нужно предоставить дополнительный бит контекста, чтобы помочь компилятору понять, что T
на самом деле <T as std::ops::BitXor>::Output
под другим именем.
Я на правильном пути? Если да, то что это будет за подсказка?
(также следующая задача - заставить функцию принимать типы IntoIterator, а не срезы - если это вообще может повлиять на решение).