【发布时间】:2020-04-20 10:12:27
【问题描述】:
我试图表达以下内容:
给定一个矩阵和两个索引增量,从矩阵中返回所有四组数字:沿行、列或某个对角线的四组数字。
use std::iter::Iterator;
use std::iter::Peekable;
use std::ops::Range;
struct Quads<'a> {
mx: &'a Vec<Vec<u32>>,
xs: &'a mut Peekable<Range<i32>>,
ys: &'a mut Peekable<Range<i32>>,
dx: i32,
dy: i32,
}
impl<'a> Quads<'a> {
fn new(mx: &'a Vec<Vec<u32>>, dx: i32, dy: i32) -> Quads<'a> {
let ys = (if dy < 0 { -3 * dy } else { 0 })..(mx.len() as i32 - if dy > 0 { 4 * dy } else { 0 });
let xs = 0..0;
Quads{
mx: mx,
xs: &mut xs.peekable(),
ys: &mut ys.peekable(),
dx: dx,
dy: dy,
}
}
}
impl<'a> Iterator for Quads<'a> {
type Item = &'a mut dyn Iterator<Item = u32>;
fn next(&mut self) -> Option<Self::Item> {
while self.xs.peek() == None && self.ys.peek() != None {
self.xs = &mut ((if self.dx < 0 { -3 * self.dx } else { 0 })..
(self.mx[0].len() as i32 - if self.dx > 0 { 4 * self.dx } else { 0 }))
.peekable();
self.ys.next();
}
let y = self.ys.peek();
if y == None {
return None;
}
let y = *y.unwrap();
let x = self.xs.next().unwrap();
Some(&mut ((x..).step_by(self.dx as usize)
.zip((y..).step_by(self.dy as usize))
.take(4)
.map(|(x,y)| self.mx[y as usize][x as usize])))
}
}
这会产生令人困惑的错误消息:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:52:27
|
52 | .map(|(x,y)| self.mx[y as usize][x as usize])))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 33:4...
--> src/main.rs:33:4
|
33 | / fn next(&mut self) -> Option<Self::Item> {
34 | | while self.xs.peek() == None && self.ys.peek() != None {
35 | | self.xs = &mut ((if self.dx < 0 { -3 * self.dx } else { 0 })..
36 | | (self.mx[0].len() as i32 - if self.dx > 0 { 4 * self.dx } else { 0 }))
... |
52 | | .map(|(x,y)| self.mx[y as usize][x as usize])))
53 | | }
| |____^
= note: ...so that the types are compatible:
expected &&mut Quads<'a>
found &&mut Quads<'a>
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 30:6...
--> src/main.rs:30:6
|
30 | impl<'a> Iterator for Quads<'a> {
| ^^
= note: ...so that the types are compatible:
expected std::iter::Iterator
found std::iter::Iterator
这似乎表明它找到了它正在寻找的相同东西。那怎么了?
预期用途
看https://projecteuler.net/problem=11
当然,这个问题可以用更直接的方式解决,但我正在学习如何用 Rust 表达复杂的事物。所以在这里我试图表达一个Quad,它是一个Iterator,它可以从那个欧拉问题中提取四倍数,其中每个四元数本身就是一个Iterator。
Quad 中的所有内容都代表Iterator 的状态。 xs 和 ys 表示“当前单元格”坐标的迭代器,从该迭代器开始下一个四元组。 next 然后尝试查看是否到达了行的末尾,并通过将xs 重新初始化为新的Iterator 前进到下一行。当ys 超出最后一行时,我们已经提取了所有四元组。
然后是这样的:
for q in Quad::new(mx, 1, 0) { ... process all quadruples along the rows }
for q in Quad::new(mx, 0, 1) { ... process all quadruples along the columns }
for q in Quad::new(mx, 1, 1) { ... process all quadruples along one diagonal }
for q in Quad::new(mx, 1, -1) { ... process all quadruples along the other diagonal }
我想我已经抓住了这个想法,但我不知道编译器不喜欢它的什么地方,以及如何继续前进。
【问题讨论】:
-
那个很奇怪的锈代码,我不太明白你想做什么。
-
@Stargateur 我已经添加了“预期用途”,如果有帮助的话。
-
@Stargateur 我想通了。想通过关于可变引用的内存管理的声明吗? (如:谁拥有可变引用对象的释放?)
标签: rust