返回一个在 Rust 中使用闭包的映射迭代器 [英] Return a map iterator which is using a closure in Rust
问题描述
我正在学习一些 Rust 来解决 Matasano 加密挑战,并且坚持将 Ceasar 密码(单字节异或")实现为迭代器.我的函数应该是这样的:
I'm learning some Rust solving the Matasano Crypto Challenges and am stuck with implementing the Ceasar cipher ("single-byte xor") as an iterator. My function is supposed to look like this:
fn ceaser_cipher_iter(data: &Vec<u8>, key :u8) -> SomeType {
data.iter().map(move |&p| p^key)
}
用 ()
替换 SomeType
,编译器告诉我它期望什么类型:core::iter::Map<core::slice::Iter<'_, u8>, [关闭 src/main.rs:59:21: 59:31]>
.经过一番折腾后,我发现我可以使用 std::slice::Iter<u8>
作为 core::slice::Iter<'_, u8>
,它留下关闭.据我了解,我使用的幼稚实验
Replacing SomeType
with ()
, the compiler tells me what type it expects: core::iter::Map<core::slice::Iter<'_, u8>, [closure src/main.rs:59:21: 59:31]>
. After some headbanging I found out I could use std::slice::Iter<u8>
for core::slice::Iter<'_, u8>
, which leaves the closure. As far as I understand, my naive experiment to use
fn ceaser_cipher_iter(data: &Vec<u8>, key :u8) -> Map<std::slice::Iter<u8>, fn(&u8)->u8 > {
data.iter().map(move |&p| p^key)
}
不能工作,因为 Rust 需要知道确切的闭包类型来为闭包分配内存(key
必须通过被 move
d 存储到闭包中).我尝试按照 建议 使用 Box
代替:
cannot work, because Rust needs to know the exact closure type to allocate the memory for the closure (key
has to be stored by being move
d into the closure). I've tried to follow the advice to use a Box
instead:
fn ceaser_cipher_iter(data: &Vec<u8>, key :u8) -> Map<std::slice::Iter<u8>, Box<Fn(&u8)->u8> > {
data.iter().map(Box::new(move |&p| p^key))
}
但是 afaict map
不支持它:
But afaict map
does not support it:
src/main.rs:59:17: 59:47 error: the trait `core::ops::FnMut<(&u8,)>` is not implemented for the type `Box<for<'r> core::ops::Fn(&'r u8) -> u8>` [E0277]
src/main.rs:59 data.iter().map(Box::new(move |&p| p^key))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:59:17: 59:47 error: the trait `core::ops::FnOnce<(&u8,)>` is not implemented for the type `Box<for<'r> core::ops::Fn(&'r u8) -> u8>` [E0277]
src/main.rs:59 data.iter().map(Box::new(move |&p| p^key))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
有没有办法返回带有闭包的地图迭代器?
推荐答案
诀窍不是将闭包装箱,而是将迭代器作为一个整体.
The trick is not to box the closure, but the iterator as a whole.
fn ceaser_cipher_iter<'a>(data: &'a Vec<u8>, key: u8) -> Box<Iterator<Item=u8> + 'a> {
Box::new(data.iter().map(move |&p| p^key))
}
请注意,因为迭代器使用借用,所以我必须添加生命周期注释,以便代码通过借用检查.
Note that because the iterator uses a borrow, I had to add lifetime annotations so that the code would pass borrow checking.
这篇关于返回一个在 Rust 中使用闭包的映射迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!