如何返回通用Map结构?

时间:2014-12-16 01:50:00

标签: closures rust

我现在不确定如果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结构吗?

2 个答案:

答案 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>