我想编写一个函数,它接受泛型类型的迭代器T,并返回一个仅给出T点特定半径内的迭代器。因为特征不能包含关联字段,并且我不想为 every实现GetXand ,所以我还将传入一个函数来检索every 的and位置。GetYTxyT
我意识到这不是最有效的空间分区/宽相碰撞检测算法,但我只是想向自己证明具有此签名的函数可以存在于借用检查规则中。
如果这个函数签名无法实现,我该如何修改它以使其工作,并且对T和 的约束/界限最少impl Iterator?
这是我的尝试:
pub fn filter<'a, T>(
world: impl Iterator<Item = &'a T>,
positions: fn(&'a T) -> (f32, f32),
near_to: (f32, f32),
radius: f32,
) -> impl Iterator<Item = &'a T> {
//We cannot access a field of the geneic item "T" directly, so we instead pass a function that retrieves that field from each "T".
let positions = world.map(positions).collect::<Vec<(f32, f32)>>();
//filter the world by the distance from the near_to point
let filter = world.enumerate().filter(move |(i, _entity)| {
//get the x,y pposition of the current entity
let (x, y) = positions[*i];
//how far is it from the near_to point?
let (dx, dy) = (x - near_to.0, y - near_to.1);
//is it within the radius?
dx * dx + dy * dy < radius * radius
});
//we don't want the index, just the entity
filter.map(|(_, entity)| entity)
}
Run Code Online (Sandbox Code Playgroud)
错误是:
1 | pub fn filter<'a, T>(world: impl Iterator<Item = &'a T>, positions: fn(&'a T) -> (f32, f32), near_to: (f32, f32), radius: f32) -> impl Iter...
| ----- move occurs because `world` has type `impl Iterator<Item = &'a T>`, which does not implement the `Copy` trait
2 | let positions = world.map(positions).collect::<Vec<(f32,f32)>>();
| -------------- `world` moved due to this method call
3 | let filter = world.enumerate().filter(move |(i, _entity)| {
| ^^^^^ value used here after move
|
note: `map` takes ownership of the receiver `self`, which moves `world`
--> D:\rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\iter\traits\iterator.rs:800:18
|
800 | fn map<B, F>(self, f: F) -> Map<Self, F>
| ^^^^
help: consider further restricting this bound
|
1 | pub fn filter<'a, T>(world: impl Iterator<Item = &'a T> + Copy, positions: fn(&'a T) -> (f32, f32), near_to: (f32, f32), radius: f32) -> impl Iterator<Item = &'a T> {
| ++++++
For more information about this error, try `rustc --explain E0382`.
Run Code Online (Sandbox Code Playgroud)
由于此操作仅过滤元素world而不考虑其他元素,因此只能使用以下命令来完成此操作.filter():
pub fn filter<'a, T>(
world: impl Iterator<Item = &'a T>,
positions: fn(&'a T) -> (f32, f32),
near_to: (f32, f32),
radius: f32,
) -> impl Iterator<Item = &'a T> {
world.filter(move |entity| {
let (x, y) = positions(entity);
let (dx, dy) = (x - near_to.0, y - near_to.1);
dx * dx + dy * dy < radius * radius
})
}
Run Code Online (Sandbox Code Playgroud)