我现在不确定如果Map
的声明发生了变化,返回通用Map
结构。新声明是:
pub struct Map<A, B, I: Iterator<A>, F: FnMut<(A,), B>> {
// some fields omitted
}
我不确定如何从函数中返回其中一个:
fn something<A: Clone, I: Iterator<A>>(iter: I) -> Map<A, (A,A), I, **what goes here**> {
iter.map(|x| (x.clone(), x))
}
我已尝试使用封面的签名我正在使用...
fn something<A: Clone, I: Iterator<A>>(iter: I) -> Map<A, (A,A), I, |A| -> (A,A)> {
iter.map(|x| (x.clone(), x))
}
然后生锈抱怨我需要明确的终身限制。我不确定为什么需要这个,但无论如何我都加了它:
fn something<'a, A: Clone, I: Iterator<A>>(iter: I) -> Map<A, (A,A), I, |A|:'a -> (A,A)> {
iter.map(|x| (x.clone(), x))
}
然后我收到错误:the trait core::ops::Fn<(A,), (A, A)> is not implemented for the type 'a |A|:'a -> (A, A)
我还没有进一步发展,此时我只是尝试随机的事情。有人可以帮我理解如何使用新的Map
结构吗?
答案 0 :(得分:3)
您无法在**what goes here**
中添加任何有意义的内容。您定义的闭包具有编译器生成的类型,您无法命名(即,直到abstract return types被实现)。
由于您的关闭不会从其环境中捕获任何内容,因此您可以使用普通函数替换它。
use std::iter::Map;
fn duplicate<T: Clone>(a: T) -> (T, T) {
(a.clone(), a)
}
fn something<A: Clone, I: Iterator<A>>(iter: I) -> Map<A, (A,A), I, fn(A) -> (A, A)> {
iter.map(duplicate as fn(A) -> (A, A)) // cast required since PR #19891
}
但是,如果你做需要捕获一些状态,那么你现在最好的办法就是定义你自己的实现FnMut
的类型。 (此示例有一个空结构,因为没有状态; call_mut
可以通过self
访问和更改结构的状态。)
#![feature(unboxed_closures)]
use std::iter::Map;
struct Duplicate;
impl<T: Clone> FnMut(T) -> (T, T) for Duplicate {
extern "rust-call" fn call_mut(&mut self, (a,): (T,)) -> (T, T) {
(a.clone(), a)
}
}
fn something<A: Clone, I: Iterator<A>>(iter: I) -> Map<A, (A,A), I, Duplicate> {
iter.map(Duplicate)
}
答案 1 :(得分:1)
这是 a 解决方案......
#![feature(unboxed_closures)]
use std::iter::Map;
use std::slice::Items;
// Box<Fn> should probably work "out-of-the-box", but I couldn't get it to...
struct Z<'a, Args, Result>(Box<Fn<Args, Result> + 'a>);
// So let's define it ourselves!
impl <'a, Args, Result> std::ops::Fn<Args, Result> for Z<'a, Args, Result> {
extern "rust-call" fn call(&self, args: Args) -> Result {
self.0.call(args)
}
}
fn do_it(a: &[int]) -> Map<&int, int, Items<int>, Z<(&int,), int>> {
// Needed to specify the parameter type, too
a.iter().map(Z(box |&: x: &int| *x + 1))
}
fn main() {
let a = vec!(1 , 2 , 3);
let b = do_it(a.as_slice());
let c: Vec<_> = b.collect();
println!("{}" , c)
}
我的工作假设是你无法直接返回Fn
(或朋友),因为它是未装箱的。未装箱的封闭尺寸不大,因此调用功能无法知道为其预留多少空间。
要解决这个问题,我们需要返回 具有大小的内容:Box
!令人惊讶的是(我暂时希望),Box<Fn>
本身并不实现Fn
,所以我创建了一个包装器结构,我可以自己实现它。
我希望将来你能够只返回一个盒子并省去包装器结构,但我继续尝试使它足够通用,足以满足现在的需要。 / p>