如何返回泛型映射结构



既然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))
}

但随后 rust 抱怨我需要明确的生命周期绑定。我不确定为什么我需要这个,但我还是添加了它:

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结构吗?

你不能

**what goes here**中放任何有意义的东西。您定义的闭包具有无法命名的编译器生成的类型(即,在实现抽象返回类型之前)。

由于闭包不会从其环境中捕获任何内容,因此您可以将其替换为正常功能。

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)
}

这是一个解决方案...

#![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,所以我创建了一个包装结构,我可以自己实现它。

我希望将来你可以只返回一个盒子并省去包装结构,但我继续尝试使其足够通用,现在就足够了。

最新更新