通用&结构中的特定功能

时间:2015-07-15 07:00:45

标签: rust

我一直在努力建立一个拥有用户输入功能的课程。虽然我实际上可以让它自己工作,但当我尝试提供一个使用默认函数的创建方法时会出现问题。说明问题的玩具示例如下所示,可以在此Playground Link

找到
fn main() {
    let a = Apply::mini(2);
    println!("{}", a.apply());
}`

struct Apply<F, I> {
    f: F,
    i: I,
}

impl<F, I> Apply<F, I> {
    fn new(f: F, i: I) -> Apply<F, I> {
        Apply{ f: f, i: i }
    }
}

impl<F, I> Apply<F, I> where F: Fn(I) -> i32 {
    fn apply(self) -> i32 {
        (self.f)(self.i)
    }
}

impl Apply<Fn(i32) -> i32, i32> {
    fn mini(i: i32) -> Apply<Fn(i32) -> i32, i32> {
        Apply::new(|x| x + 1, i)
    }
}

这个实现正确地抱怨Fn(i32) - &gt; i32未分级。我能想到绕过它的唯一方法就是把它作为一个类型参数拉出来,但这似乎也不起作用。

1 个答案:

答案 0 :(得分:3)

Rust中的未装箱闭包实现为实现某些特征的匿名类型。 “匿名”当然意味着它们无法命名 - 因此不可能(at least now)通过函数的值返回未装箱的闭包。

有两种方法可以解决这个特定问题。首先,因为mini()中的闭包不会捕获任何内容,所以可以使用常规函数:

impl Apply<fn(i32) -> i32, i32> {
    fn mini1(i: i32) -> Apply<fn(i32) -> i32, i32> {
        fn add_one(x: i32) -> i32 { x + 1 }
        Apply::new(add_one, i)
    }
}

其次,如果您确实需要使用捕获闭包,则必须使用Box

impl Apply<Box<Fn(i32) -> i32>, i32> {
    fn mini2(i: i32) -> Apply<Box<Fn(i32) -> i32>, i32> {
        Apply::new(Box::new(|x| x + 1), i)
    }
}

我不知道为什么,但为了这个工作我必须专门为盒子实现apply2()方法(这对我来说真的看起来像个bug):

impl<I> Apply<Box<Fn(I) -> i32>, I> {
    fn apply2(self) -> i32 {
        (self.f)(self.i)
    }
}

(全部试试here

更新: here是@ker的代码链接,不需要第二个apply方法。它使用Deref的一个很好的技巧,允许apply()与盒装特征对象一起使用。